大话快排 和 归排的渊源

news/2024/5/17 18:26:27 标签: 快速排序, 分治算法, 归并排序

一:起因

(1)包括冒泡算法、快排算法、插入排序算法等;还有基于外部排序的归并排序(以二路归并排序为例 )

但是基本上在一个数量级上;

(2)

mergesort (归并排序) 可以应用在外部排序,这与基于内存的quicksort(快速排序)略有不同,他们的算法复杂度都可以达到O(nlogn)

(3)mergesort 是稳定的排序算法,需要额外的空间开销O(n);quicksort 是非稳定的排序算法,额外的空间开销O(1);两者的核心思想都来源与分支的策略(divide and conquer),一个是merge 过程,一个是partition过程。

二:详解

(1)归并排序

归并操作的工作原理如下:

第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列(或者只申请一次,多次使用空间)

第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置

第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置

重复步骤3直到某一指针超出序列尾

第四步:将另一序列剩下的所有元素直接复制到合并序列尾   ----- 分治策略

图解:


(2)代码

struct node
{
	int key;
	int num;
}n[N],t[N];
void merge(struct node s[], int low, int mid, int high, struct node temp[])
{// 相当于合并 同一个数组 中的两段有序的序列
	int i,j,k;
	i=low,j=mid+1,k=0;
	while (i<=mid&&j<=high)
	{
		if (s[i].key<=s[j].key)
		{
			temp[k].key = s[i].key;
			i ++;
			k ++;
		}
		else
		{
			temp[k].key = s[j].key;
			j ++;
			k ++;
		}
	}// 剩下的添加到末位
	while (i<=mid)
	{
		temp[k++].key = s[i++].key;//和if里面一样的效果
	}
	while (j<=high)
	{
		temp[k++].key = s[j++].key;
	}
<span style="white-space:pre">	</span>// 把temp里排序好的放到原始数组中
	for (i=0; i<k; i++)
	{
		s[low+i] = temp[i];
	}
}

void merge_sort(struct node s[],int low,int high,struct node temp[])
{
	int mid;	
	if (low < high)
	{
		mid = low + (high-low)/2;
		merge_sort(s,low,mid,temp);//左边分割 、归并排序
		merge_sort(s,mid+1,high,temp);//右边分割、归并排序
		merge(s,low,mid,high,temp);//
	}
}

小结:可以将A,B组各自再分成二组。依次类推,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的二个小组就可以了。这样通过先递归的分解数列,再合并数列就完成了归并排序

(3)快速排序

快速排序(Quicksort)是对冒泡排序的一种改进。由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。 ----- 分治策略

每一趟快速排序的算法是 partition算法: (而整个quicksort 是根据每一次返回的part下标值,进行下一轮的partition,直到low >= high)
1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;
2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];
3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]互换;
4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;
5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。

图解:


(4)代码

int paritition(data b[], int left, int right)//从小到大  
{  
    if(left < right)  
    {  
        int key = b[left].key;  
        int low = left;  
        int high = right;  
        while(low < high)  
        {  
            while(low < high && b[high].key >= key)  
            {  
                high--;  
            }  
            b[low].key = b[high].key;//若是没有找到比key 小的(即由于low = high 而退出循环),  
            //则这句话的意思是把自己赋值给自己。  
  
            while(low < high && b[low].key <= key)  
            {  
                low++;  
            }  
            b[high].key = b[low].key;//若是没有找到比key 大的(即由于low = high 而退出循环),  
            //则这句话的意思……(分情况:当上面的找到比key小的了,则移动;当上面也没有找到,则自己赋值给自己)。  
        }  
  
        b[low].key = key;  
        return low;
    }  
    return 0;  
}
分治算法

void quick_sort(int s[], int l, int r)
{
	if (l < r)
    {
		int i = partition(s, l, r);//partition 算法
		quick_sort1(s, l, i - 1); // 递归调用 
		quick_sort1(s, i + 1, r);
	}
}


http://www.niftyadmin.cn/n/865479.html

相关文章

说说如何利用 Oracle 命令来解决函数运行错误

1 问题 自定义了一个 Oracle 函数。编译正常&#xff1b;使用 PL/SQL Developer 的 Test 窗口模式&#xff0c;测试通过。但 Java 直接调用失败&#xff1b;使用 PL/SQL Developer 的 SQL 窗口模式&#xff0c;执行失败。 没有有效的错误提示信息。 2 分析 肯定是函数本身有…

大话 回调函数 和 枚举

一&#xff1a;起因 &#xff08;1&#xff09;接着上一篇博客 大话 函数指针 和 指针函数 &#xff08;2&#xff09;对指针的应用是C语言编程的精髓所在&#xff0c;而回调函数就是C语言里面对函数指针的高级应用 &#xff08;3&#xff09;回调函数可以实现代码具体实…

大话 函数指针 和 枚举这对鸳鸯

一&#xff1a;起因 &#xff08;1&#xff09;函数指针是指向函数的指针变量&#xff0c;即本质是一个指针变量&#xff0c;是一个指向函数&#xff08;可能是代码区&#xff09;的首地址的指针&#xff0c;正如我们都知道&#xff0c;数组名就是指向数组第一个元素的常量指针…

说说在 Linux 中,如何使用非 root 账户执行 cd 命令

可以使用 sudo &#xff0c;它允许一个已授权的用户以超级用户或者其它用户的角色来运行命令。 未使用 sudo 之前&#xff1a; [jenkinfj1wdb jenkins]$ cd secrets -bash: cd: secrets: 权限不够 执行 sudo 指令&#xff1a; sudo -s-s 表示执行指定的 shell。 使用 sudo 之…

大数据之道 HMM系列

一&#xff1a;HMM解码问题&#xff08;1&#xff09;给定一个观察序列OO1O2...OT,和模型μ&#xff08;A,B,π&#xff09;&#xff0c;如何快速有效地选择在一定意义下“最优”的状态序列Qq1q2...qT&#xff0c;使该状态最好地解释观察序列。 &#xff08;2&#xff09;最可能…

大数据之道 HMM系列二(成长)

一&#xff1a;HMM解码问题&#xff08;1&#xff09;编程深处无非就是算法和结构&#xff0c;以及各种架构和版本的管理&#xff08;如Git管理&#xff09;&#xff0c;因此作为程序员算法这一关是绕不过去的&#xff1b; &#xff08;2&#xff09;关于算法&#xff0c;个人比…

说说 ORA-20000: ORU-10027: buffer overflow, limit of 1000 bytes 问题的解决方法

在 PL/SQL Developer 的 Command Window 中&#xff0c;执行 SQL 指令&#xff0c;抛出 ORA-20000: ORU-10027: buffer overflow, limit of 1000 bytes 异常。 1 分析 由于 DBMS_OUTPUT.PUT_LINE 输出的调试信息太多&#xff0c;超出 1000 字节的限制。 2 解决 执行命令前&…

大数据处理之道 (MATLAB 篇三)

一:起因 (1)最近一直在处理大数据,从MB ----> GB的变化,是一次质的飞跃,相应的工具也在变 从widows到linux,从单机单核 到 hadoop多节点的计算 (2)问题来了,面对海量的数据,如何从中挖掘实用的信息或者发现潜在的现象,可视化工具可能是必不可少的 ; (3)可视化…