分治与减治算法实验:题目2 排序中分治法的程序设计

目录

前言:

一、实验内容

二、实验目的

三、实验步骤

四、实验过程

1、算法分析

2、写出伪代码

3、代码实现

4、代码详解

5、用例测试

6、复杂度分析

总结


前言:

分治法是一种将复杂问题分解为若干个相同或相似的子问题,然后递归地求解子问题,最后将子问题的解合并为原问题的解的算法设计思想。减治法是一种将复杂问题简化为规模较小的同类问题,然后递归地求解简化后的问题,最后得到原问题的解的算法设计思想。分治法和减治法都是利用递归技术实现的算法。

排序是计算机科学中最基本也最重要的问题之一,它的目的是将一组无序的数据按照某种规则排列成有序的数据。排序中有许多经典的分治法和减治法的应用,例如快速排序、归并排序、堆排序等。这些排序算法都有各自的优缺点,需要根据不同的场景和需求选择合适的算法。

本实验旨在通过排序中分治法的程序设计,掌握分治法和减治法在排序问题上的应用,了解不同排序算法的原理、步骤、性能和特点,能够使用高级语言实现和测试这些排序算法,并能够分析和比较它们之间的异同。

本文中使用的语言是C语言,使用的ide是devc++
 

一、实验内容

给出一个初始序列,分别用归并法和快速排序两种分治法将所给序列变为有序序列,输出结果,输出是要有文字说明。请任选一种语言编写程序实现上述算法,并分析其算法复杂度

二、实验目的

(1)掌握归并排序和快速排序的划分方法;

(2)掌握归并排序和快速排序的具体分治策略;

(3)在掌握的基础上编程两种排序方法的实现过程。

三、实验步骤

1、写出伪代码进行算法描述

2、使用c++编写程序完成上述算法

3、使用测试用例对算法进行测试

4、对算法的复杂度进行分析

四、实验过程

1、算法分析

归并排序和快速排序都是分治算法的经典代表。两种算法都通过递归来实现,过程非常相似。归并排序非常稳定,但不是原地排序;快速排序,是原地排序算法,应用得更加广泛。

归并排序:将序列分成两个子序列,对每个子序列进行递归排序,然后将两个排好序的子序列合并成一个有序序列。
快速排序:选取一个基准元素,将小于等于基准元素的元素放到左边,大于基准元素的元素放到右边,然后对左右两个子序列递归进行快速排序。

2、写出伪代码

归并排序:

merge_sort(arr, p, r)
    if p < r
        q = (p + r) / 2
        merge_sort(arr, p, q)
        merge_sort(arr, q+1, r)
        merge(arr, p, q, r)

merge(arr, p, q, r)
    n1 = q - p + 1
    n2 = r - q
    let L[1..n1+1] and R[1..n2+1] be new arrays
    for i = 1 to n1
        L[i] = arr[p + i - 1]
    for j = 1 to n2
        R[j] = arr[q + j]
    L[n1+1] = infinity
    R[n2+1] = infinity
    i = 1
    j = 1
    for k = p to r
        if L[i] <= R[j]
            arr[k] = L[i]
            i = i + 1
        else arr[k] = R[j]
            j = j + 1

快速排序:

quick_sort(arr, low, high)
    if low < high
        pivot_location = partition(arr, low, high)
        quick_sort(arr, low, pivot_location - 1)
        quick_sort(arr, pivot_location + 1, high)

partition(arr, low, high)
    pivot_item = arr[low]
    left_mark = low + 1
    right_mark = high
    done = False
    while not done
        while left_mark <= right_mark and arr[left_mark] <= pivot_item
            left_mark += 1
        while right_mark >= left_mark and arr[right_mark] >= pivot_item
            right_mark -= 1
        if right_mark < left_mark
            done = True
        else swap arr[left_mark] with arr[right_mark]
    swap arr[low] with arr[right_mark]
    return right_mark

3、代码实现

#include <iostream>
using namespace std;

void merge(int arr[], int l, int m, int r) {
   int i, j, k;
   int n1 = m - l + 1;
   int n2 = r - m;

   int L[n1], R[n2];

   for (i = 0; i < n1; i++)
       L[i] = arr[l + i];
   for (j = 0; j < n2; j++)
       R[j] = arr[m + 1 + j];

   i = 0;
   j = 0;
   k = l;
   while (i < n1 && j < n2) {
       if (L[i] <= R[j]) {
           arr[k] = L[i];
           i++;
       }
       else {
           arr[k] = R[j];
           j++;
       }
       k++;
   }

   while (i < n1) {
       arr[k] = L[i];
       i++;
       k++;
   }

   while (j < n2) {
       arr[k] = R[j];
       j++;
       k++;
   }
}

void mergeSort(int arr[], int l, int r) {
   if (l >= r) {
       return;
   }
   int m = l + (r - l) / 2;
   mergeSort(arr, l, m);
   mergeSort(arr, m + 1, r);
   merge(arr, l, m, r);
}

int partition(int arr[], int low, int high) {
   int pivot = arr[high];
   int i = (low - 1);

   for (int j = low; j <= high - 1; j++) {
       if (arr[j] < pivot) {
           i++;
           swap(arr[i], arr[j]);
       }
   }
   swap(arr[i + 1], arr[high]);
   return (i + 1);
}

void quickSort(int arr[], int low, int high) {
   if (low < high) {
       int pi = partition(arr, low, high);
       quickSort(arr, low, pi - 1);
       quickSort(arr, pi + 1, high);
   }
}
int main() {
   // 归并排序
   cout << "归并排序" << endl;
   cout << "请输入待排序序列长度:";
   int n;
   cin >> n;
   cout << "请输入待排序序列:";
   int a[n];
   for (int i = 0; i < n; i++) {
       cin >> a[i];
   }
   mergeSort(a, 0, n - 1);
   cout << "排序后的序列为:";
   for (int i = 0; i < n; i++) {
       cout << a[i] << " ";
   }
   
   // 快速排序
   cout << endl << endl << "快速排序" << endl;
   cout << "请输入待排序序列长度:";
   
   cin >> n;
   
   cout << "请输入待排序序列:";
   
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    quickSort(a, 0, n - 1);
    cout << "排序后的序列为:";
    for (int i = 0; i < n; i++) {
        cout << a[i] << " ";
    }
    return 0;
}

4、代码详解

上述代码实现使用C语言实现了归并排序和快速排序两种分治算法

归并排序是一种分治算法,它将待排序的序列分成两个子序列,对每个子序列进行递归排序,然后将两个排好序的子序列合并成一个有序序列。具体来说,mergeSort函数实现了归并排序。mergeSort函数的参数包括待排序数组arr、数组左端点l和右端点r。如果l>=r,则返回;否则,计算中间点m=(l+r)/2,对左半部分arr[l…m]进行递归排序,对右半部分arr[m+1…r]进行递归排序,最后将左右两个排好序的子序列合并成一个有序序列。

快速排序也是一种分治算法,它选取一个基准元素,将小于等于基准元素的元素放到左边,大于基准元素的元素放到右边,然后对左右两个子序列递归进行快速排序。具体来说,partition函数实现了快速排序。partition函数的参数包括待排序数组arr、数组左端点low和右端点high。首先选取基准元素pivot=arr[high],然后从low到high-1遍历数组arr。如果arr[j]<pivot,则将arr[i]和arr[j]交换,并将i加1。最后将arr[i+1]和arr[high]交换,并返回i+1

5、用例测试

6、复杂度分析

  • 归并排序:将待排序序列分成若干个子序列,每个子序列都是有序的。然后再将有序子序列合并成整体有序序列。归并排序的时间复杂度为O(nlogn),空间复杂度为O(n)。
  • 快速排序:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。快速排序的时间复杂度为O(nlogn),空间复杂度为O(logn)。

当n趋近于无穷大时,归并排序和快速排序的时间复杂度都是O(nlogn)。归并排序的时间复杂度始终都是O(nlogn),而快速排序虽然最坏情况下时间复杂度为O(n^2),但平均情况下时间复杂度为O(nlogn),最坏情况发生的概率也比较小,因此应用得更加广泛 


总结

这篇文章介绍了分治法和减治法的算法设计思想,以及它们在排序问题中的应用。文章提到了许多经典的分治法和减治法的应用,例如快速排序、归并排序、堆排序等。这些排序算法都有各自的优缺点,需要根据不同的场景和需求选择合适的算法。文章还介绍了本实验的目的和内容,即通过排序中分治法的程序设计,掌握分治法和减治法在排序问题上的应用,了解不同排序算法的原理、步骤、性能和特点,能够使用高级语言实现和测试这些排序算法,并能够分析和比较它们之间的异同。

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,让我来为您提供一份关于运用分治法解决归并排序实验报告的指南。 一、算法描述与程序 1. 算法描述 归并排序的基本思路是将待排序的数组不断地二分,直到每个子数组只剩下一个元素,然后将这些子数组两两合并,直到最终得到一个有序的数组。 具体的操作步骤如下: 1. 将待排序的数组二分为两个子数组,直到每个子数组只剩下一个元素。 2. 将两个子数组合并为一个有序的数组,合并的方法是比较两个子数组的第一个元素,将较小的元素放入新的数组,然后将该元素所在的子数组的指针向后移动一位,直到有一个子数组的所有元素都被放入了新的数组,再将剩余的元素依次放入新的数组。 3. 重复步骤2,直到所有的子数组都被合并成一个有序的数组。 2. 程序实现 下面是用 Python 实现归并排序的程序: ```python def merge_sort(arr): if len(arr) <= 1: return arr mid = len(arr) // 2 left_arr = arr[:mid] right_arr = arr[mid:] left_arr = merge_sort(left_arr) right_arr = merge_sort(right_arr) result = [] i = j = 0 while i < len(left_arr) and j < len(right_arr): if left_arr[i] < right_arr[j]: result.append(left_arr[i]) i += 1 else: result.append(right_arr[j]) j += 1 result += left_arr[i:] result += right_arr[j:] return result ``` 二、测试分析与总结 1. 测试分析 为了测试归并排序的性能,我们可以使用 Python 自带的 time 模块来计算程序的执行时间。下面是测试代码: ```python import random import time arr = [random.randint(0, 10000) for _ in range(1000)] start_time = time.time() sorted_arr = merge_sort(arr) end_time = time.time() print('排序前:', arr) print('排序后:', sorted_arr) print('排序耗时:', end_time - start_time, '秒') ``` 运行测试代码后,我们可以得到排序前的随机数组、排序后的数组以及程序的执行时间。由于归并排序的时间复杂度为 O(nlogn),因此在处理较大的数据集时,归并排序具有一定的优势。 2. 总结 归并排序是一种基于分治法排序算法,它的主要思想是将待排序的数组不断地二分,直到每个子数组只剩下一个元素,然后将这些子数组两两合并,直到最终得到一个有序的数组。归并排序具有稳定性,适用于大型数据集合,并且是一种相对高效的排序算法。 三、设计分析 1. 时间复杂度 归并排序的时间复杂度为 O(nlogn),其 n 是待排序数组的长度。这是因为归并排序的主要操作是将数组不断地二分,直到每个子数组只剩下一个元素,这个过程的时间复杂度为 O(logn);然后将这些子数组两两合并,合并的时间复杂度为 O(n),因此总的时间复杂度为 O(nlogn)。 2. 空间复杂度 归并排序的空间复杂度为 O(n),其 n 是待排序数组的长度。这是因为在归并排序的过程需要创建一个临时数组来存储合并后的数组,其长度为待排序数组的长度。 3. 稳定性 归并排序是一种稳定的排序算法,因为在合并两个子数组时,如果两个子数组有相同的元素,那么先出现的元素一定在合并后的数组排在先面,不会改变它们原本的相对位置。 四、总结 本篇实验报告介绍了运用分治法解决归并排序算法描述、程序、测试分析与总结、设计分析等方面的内容。归并排序是一种基于分治法排序算法,具有稳定性、适用于大型数据集合,并且是一种相对高效的排序算法。在实际应用,我们可以根据数据规模和性能要求选择不同的排序算法

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值