大话快排 和 归排的渊源

来源:互联网 发布:ubuntu上一目录 编辑:程序博客网 时间:2024/04/28 16:18

一:起因

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

5 0
原创粉丝点击