递归与分治之合并排序和快速排序

合并排序

合并排序的基本思想是:将待排序元素分为大小大致相同的两个子集,分别对两个子集合进行排序,最终将排序好的子集合合并为所要求的排好序的集合。

具体步骤可以通过下列的动图查看:(引用自https://blog.csdn.net/li528405176/article/details/86615003)
在这里插入图片描述

void merge_sort_recursive(int arr[], int reg[], int start, int end)//仅列举函数 
{
    if (start >= end)
        return;
    int len = end - start, mid = (len >> 1) + start;
    int start1 = start, end1 = mid;
    int start2 = mid + 1, end2 = end;
    merge_sort_recursive(arr, reg, start1, end1);
    merge_sort_recursive(arr, reg, start2, end2);
    int k = start;
    while (start1 <= end1 && start2 <= end2)
        reg[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++];
    while (start1 <= end1)
        reg[k++] = arr[start1++];
    while (start2 <= end2)
        reg[k++] = arr[start2++];
    for (k = start; k <= end; k++)
        arr[k] = reg[k];
}

void merge_sort(int arr[], const int len) {
    int reg[len];
    merge_sort_recursive(arr, reg, 0, len - 1);
}

合并排序的最坏和平均复杂度均为O(nlogn)

快速排序

快速排序是最常用的排序算法。其原理如下:

1.设定一个基准A(一般是以第一个元素为基准),把大于这个基准A的数放在这个基准后,小于这个基准A的数字放在这个基准前;

2.对大于和小于基准A的部分分别使用步骤1,设定新的基准,划分数组,直到数组中只有一个元素为止。

这样说起来有些抽象,我们利用一个例子具体说明排序过程:

我们现在有无序的数组{6,7,5,2,5,8},第一次循环我们以6为基准。

首先,设置两个变量i,j记录位置(位置从0—5),初始时i=1,j=5,如图:
在这里插入图片描述
现在从后往前找第一个小于6的数字,j现在指向8,大于6,j减小,指向5,此时5小于6,如图:
在这里插入图片描述
交换i和j指向的元素位置,7和5交换位置得到结果如下:
在这里插入图片描述
现在从前往后找第一个大于6的数字,显然到7之前没有比6大的数字,而从后往前找第一个小于6的数字时,找到了2,也就是此时i>j,如图:
在这里插入图片描述
按理说i在前半部分,j在后半部分,但此时i>j了,因此,我们已经确定了,在j处(我们要保证从小到大排列 ,i指向的此时大于6),之前的数字小于6,之后的数字大于6,我们将6置换到j处,得到:
在这里插入图片描述
这就是一次快速排序的结果,之后我们分别再对前半部分和后半部分使用快速排序,直到每个数组只有一个数字的时候,我们的快速排序就完成了。

代码如下:

void QuickSort(int a[],int start,int last)
{
	int i=start;
	int j=last;
	int temp=a[i];
if(i<j)
{
	while(true)
	{
		while(a[i]<x)
		{
		i++;
		}
		while(a[j]>x)
		{
		j--;
		}	
		if(i>=j) break;
		int m=a[i];
		a[i]=a[j];
		a[j]=m;
	}
	a[i]=a[j];
	a[j]=temp;
	QuickSort(a,start,j-1);
	QuickSort(a,j+1,last);
}	
}

快速排序的最坏时间复杂度:O(n^2),平均时间复杂度为O(nlogn);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值