大话快排 和 归排的渊源

一:起因

(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);
	}
}

时间: 2024-07-30 13:38:18

大话快排 和 归排的渊源的相关文章

Java常见的几种排序算法-插入、选择、冒泡、快排、堆排等

本文就是介绍一些常见的排序算法.排序是一个非常常见的应用场景,很多时候,我们需要根据自己需要排序的数据类型,来自定义排序算法,但是,在这里,我们只介绍这些基础排序算法,包括:插入排序.选择排序.冒泡排序.快速排序(重点).堆排序.归并排序等等.看下图: 给定数组:int data[] = {9,2,7,19,100,97,63,208,55,78} 一.直接插入排序(内部排序.O(n2).稳定) 原理:从待排序的数中选出一个来,插入到前面的合适位置. [java] view plain copy

常见的几种排序算法-插入、选择、冒泡、快排、堆排等

排序是一个非常常见的应用场景,很多时候,我们需要根据自己需要排序的数据类型,来自定义排序算法,但是,在这里,我们只介绍这些基础排序算法,包括:插入排序.选择排序.冒泡排序.快速排序(重点).堆排序.归并排序等等.看下图: 给定数组:int data[] = {9,2,7,19,100,97,63,208,55,78} 一.直接插入排序(内部排序.O(n2).稳定) 原理:从待排序的数中选出一个来,插入到前面的合适位置. package com.xtfggef.algo.sort; public

快排,堆排与归并排序

快排: Parition函数用于进行一次快排,本次快排将某个元素放在它应该呆在的位置pos.pos左侧全比它小,pos右侧全比它大. Parition中,设置low指针与high指针,以待排元素为标杆,判断high指向元素是否大于待排元素,若小于则与low指向的元素交换,并切换到low指针.low指针此时指向刚交换过来的元素,其一定小于待排元素,然后low自加直到low指向的元素大于待排元素,此时再与high指向的元素交换,high指向的元素为之前一次low - high交换前low指向的元素:

快排,冒泡排,选择排序,希尔排序

package cn.hncu.dataStruct; public class SortMethods { /* 算法好坏的评价指标(一般只在n值非常大的时候才会考虑,如n取10万): * 1.时间复杂度: 通俗点,就是指程序运行的快慢(时间)---通常用计算机的运算(算术,赋值)次数来代替 * 2.空间复杂度: 占用内存空间的大小---通常用程序中使用了多少变量(栈内存.堆内存),这些变量总共占了多少内存 */ public static void main(String[] args) {

排序算法的实现(归并,快排,堆排,希尔排序 O(N*log(N)))

今天跟着左老师的视频,理解了四种复杂度为 O(N*log(N))的排序算法,以前也理解过过程,今天根据实际的代码,感觉基本的算法还是很简单的,只是自己写的时候可能一些边界条件,循环控制条件把握不好. //对于一个int数组,请编写一个选择冒泡算法,对数组元素排序. //给定一个int数组A及数组的大小n,请返回排序后的数组. //测试样例: //[1, 2, 3, 5, 2, 3], 6 //[1, 2, 2, 3, 3, 5] #include <iostream> using namesp

python 快排,堆排,归并

#归并排序def mergeSort(a,L,R) :    if(L>=R) :        return    mid=((L+R)>>1)    mergeSort(a,L,mid)    mergeSort(a,mid+1,R)    p=L    q=mid+1    t=[]    while(p<=mid and q<=R) :        if a[p]<=a[q] :            t.append(a[p])            p+=

选择排序,快排,冒排

选择排序 //基本思想:选择排序(Selection-sort)是一种简单直观的排序算法. //它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置, //然后,再从剩余未排序元素中继续寻找最小(大)元素, //然后放到已排序序列的末尾.以此类推,直到所有元素均排序完毕 [7, 6, 5, 3, 1, 9, 4] ------------------------ [1, 6, 5, 3, 7, 9, 4] [1, 3, 5, 6, 7, 9, 4] [1, 3, 4, 6

一条线公排2017公排模式开发

一条线公排见点奖系统开发找陈生:135-7001-0501(可微电),一条线公排制度分析,一条线公排进四升一,一条线公排 2017,全球一条线公排制度,一条线奖金制度,公排制度图解 合作公排系统是近期微商城中一种十分火爆的挣钱形式,之所以如此的火爆,是因为这个形式彰显出的公正,比方曩昔是依照谁先进来来分推行等级的,可是公排是依照分销商的才能来排队取钱的,所以说这种公正的挣钱形式更为微商们所推重. 一条线公排直销系统单轨制直销形式会员利益准则举例说明; 初级会员;一条线公排直销系统单轨制直销形式经

错排公式 错排(加组合)

递推的方法推导错排公式 当n个编号元素放在n个编号位置,元素编号与位置编号各不对应的方法数用M(n)表示,那么M(n-1)就表示n-1个编号元素放在n-1个编号位置,各不对应的方法数,其它类推. 第一步,把第n个元素放在一个位置,比如位置k,一共有n-1种方法; 第二步,放编号为k的元素,这时有两种情况.1,把它放到位置n,那么,对于剩下的n-2个元素,就有M(n-2)种方法;2,不把它放到位置n,这时,对于这n-1个元素,有M(n-1)种方法; 综上得到 M(n)=(n-1)[M(n-2)+M