c++归并排序代码及原理

归并排序

归并排序是多次将相邻两个或两个以上的有序表合并成一个新的有序表。

最简单的 归并 是将相邻 两 个有序的子表 合并成一个有序的表,即 二路归并排序 。

一次二路 归并:将 两个位置相邻的记录有序子 序列归并为一个记录的有序序列。

每一趟归并的时间复杂度为O(n),总共需要进行[long2n]趟(向上取整)。

所以二路归并排序的时间复杂度为O(nlog2n)

所以空间复杂 度为Ο(n)。


三 路 归并的时间复杂度为O(nlog3n)

nlog 3 n=nlog 2 n/log 2 3=O(nlog 2 n)

可以看出时间复杂度为同一级别,并不会因为路数的增加而增加时间复杂度。


void merge(vector<int>& a,int low,int mid,int high){
     int* b = new int[high-low+1];
	 int i=low,j=mid+1,k=0;
	while(i<=mid&&j<=high)
		if(a[i]<=a[j]){b[k]=a[i];i++;k++;}
	    else{b[k]=a[j];j++;k++;}
	while (i<=mid) // 将第1 段余下部分复制到b
		{ b[k]=a[i]; i++;k++; }
	while (j<=high) // 将第2 段余下部分复制到b
		{ b[k]=a[j]; j++;k++; }
	for (k=0,i=low;i<=high;k++,i++) // 将b 复制回a中
		a[i]=b[k];
    delete [] b;
}
void mergepass(vector<int>& a,int length,int n){ //length表示每个片段的段长度
  int i;
	for(i = 0; i+2*length-1<n;i= i+2*length){ //归并长度为length的两个子序列
	   merge(a,i,i+length-1,i+2*length-1);
   }
	if(i+length -1<n)   //最后的子表长度可能小于length
		merge(a,i,i+length-1,n-1);  
}
void merge_sort(vector<int>& a, int n){
	int length;
	for(length =1;length<n;length = 2*length){//log2(n)趟
		mergepass(a,length,n);
	}
}
int main()
{
	vector<int> data{ 61, 17, 29, 22, 34, 60, 72, 21, 50, 1, 62 };
	int n = data.size();
	//SI_sort(data,n);
	//shell_sort(data,n);
	//Bibble_sort(data,n);
	//quickSort(data,0,n-1);
	//select_sort(data,n);
	//head_sort(data,n);
	merge_sort(data,n);
    for (int i = 0; i < n; i++)
    {
        cout << data[i]<<" ";
    }
   return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
归并排序是一种基于分治法的排序算法,它的基本思路是将待排列不断地划分更小的子列,直到每个子列只有一个元素,然后再将这些子列两两合并,直到最终得到一个有序列。 具体的归并排序算法步骤如下: 1. 将待排列不断地二分划分,直到每个子列只有一个元素。 2. 将相邻两个列进行合并合并时比较两个列的元素大小,将较小的元素放在列中。 3. 重复步骤2,直到所有的子列都合并一个有序列。 归并排序的关键在于合并操作,合并操作的实现可以使用一个辅助数组来存储合并后的结果。具体的合并操作步骤如下: 1. 创建一个与待排列大小相同的辅助数组。 2. 将待排列的两个列分别赋值给辅助数组的两个列。 3. 使用两个指针分别指向辅助数组的两个列的起始位置,比较两个指针所指向的元素大小,将较小的元素放入原始列中,并将指针向后移动一位。 4. 重复步骤3,直到其中一个列的元素全部放入原始列中。 5. 将另一个列中剩余的元素依次放入原始列中。 下面是C++实现归并排序代码示例: ```cpp #include <iostream> using namespace std; // 合并两个有序列 void merge(int arr[], int left, int mid, int right) { int i = left; // 左子列的起始位置 int j = mid + 1; // 右子列的起始位置 int k = 0; // 辅助数组的起始位置 int* temp = new int[right - left + 1]; // 辅助数组 // 比较两个列的元素大小,将较小的元素放入辅助数组中 while (i <= mid && j <= right) { if (arr[i] <= arr[j]) { temp[k++] = arr[i++]; } else { temp[k++] = arr[j++]; } } // 将剩余的元素放入辅助数组中 while (i <= mid) { temp[k++] = arr[i++]; } while (j <= right) { temp[k++] = arr[j++]; } // 将辅助数组的元素复制回原始列 for (int m = 0; m < k; m++) { arr[left + m] = temp[m]; } delete[] temp; } // 归并排序 void mergeSort(int arr[], int left, int right) { if (left < right) { int mid = (left + right) / 2; mergeSort(arr, left, mid); // 对左子列进行归并排序 mergeSort(arr, mid + 1, right); // 对右子列进行归并排序 merge(arr, left, mid, right); // 合并两个有序列 } } int main() { int arr[] = {5, 2, 8, 3, 1, 6}; int n = sizeof(arr) / sizeof(arr[0]); mergeSort(arr, 0, n - 1); cout << "Sorted array: "; for (int i = 0; i < n; i++) { cout << arr[i] << " "; } cout << endl; return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值