八大排序算法

合集下载

深入浅出-C语言8种经典排序算法

深入浅出-C语言8种经典排序算法

C语言——8种经典排序算法1.排序算法的稳定性分析:若待排序的序列中,存在多个具有相同关键字的记录,经过排序,这些记录的相对次序保持不变,则称该算法是稳定的;若经排序后,记录的相对次序发生了改变,则称该算法是不稳定的。

(1)冒泡排序冒泡排序就是把小的元素往前调或者把大的元素往后调。

比较是相邻的两个元素比较,交换也发生在这两个元素之间。

所以,如果两个元素相等,我想你是不会再无聊地把他们俩交换一下的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。

(2)选择排序选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个元素不用选择了,因为只剩下它一个最大的元素了。

那么,在一趟选择,如果当前元素比一个元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。

比较拗口,举个例子,序列5 8 5 2 9,我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。

(3)插入排序插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。

当然,刚开始这个有序的小序列只有1个元素,就是第一个元素。

比较是从有序序列的末尾开始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。

如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。

所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。

(4)快速排序快速排序有两个方向,左边的i下标一直往右走,当a[i] <= a[center_index],其中center_index 是中枢元素的数组下标,一般取为数组第0个元素。

算法_八大排序算法总结

算法_八大排序算法总结

算法_⼋⼤排序算法总结最近笔试⾯试中经常考到排序算法,及其对应的时间复杂度和空间复杂度分析,现做如下总结。

⼀,冒泡排序思想:对于0~n-1,依次⽐较相邻两个数,前者⽐后者⼤就交换,⼀轮后A[n-1]是最⼤数,在对0~n-2执⾏以上步骤,则A[n-2]是第⼆⼤的数,循环执⾏上⾯的步骤即可,形象的可以理解为⼤的数⼀个个冒到后⾯去,所以叫冒泡排序。

⽰意图:⾸先6和3⽐较,6⽐3⼤,交换6和5⽐较,交换6和7⽐较,不⽤交换依次执⾏以上步骤,第⼀轮后,序列变为接着,在0到n-2上执⾏以上步骤⼀轮过后,则变为依次执⾏以上步骤,最后序列为时间复杂度: O(n^2)空间复杂度:O(1)代码:1class BubbleSort {2public:3int* bubbleSort(int* A, int n)4 {5int temp;6// write code here7for(int i = 0; i < n; i++)8 {9for(int j = 0; j < n - i - 1; j++)10 {11if(A[j] > A[j+1])12 {13 temp = A[j];14 A[j] = A[j + 1];15 A[j + 1] = temp;16 }17 }1819 }20return A;21 }22 };⼆,选择排序思想:在序列中依次选择最⼩值放到最前端,重复以上步骤,只到排序完成⽰意图:最⼩数为0,放到最前端1到n-1最⼩数为1,放到最前端依次执⾏以上步骤,最后为时间复杂度:O(n^2)空间复杂度:O(1)代码:1class SelectionSort {2public:3int* selectionSort(int* A, int n)4 {5// write code here6//从前往后依次放⼊为排序的数组的最⼩值7int min_b;8int temp;9for(int i = 0; i < n - 1; i++)10 {11 min_b = i;12for(int j = i; j < n; j++) //寻找最⼩值13 {14if(A[min_b] > A[j])15 min_b = j;1617 }18 temp = A[i];19 A[i] = A[min_b];20 A[min_b] = temp;21 }22return A;23 }24 };三,插⼊排序思想:对于数组A[n],保证前⾯的A[0]~A[m]是排序好的,再把A[m+1]插⼊到前⾯排好序的序列中,m递增,知道m=n-2⽰意图:原始序列为:6和5⽐较,6⽐5⼤,要交换接下来把3插⼊到前⾯排好序的序列中,⾸先3和6⽐,6⼤,后移⼀位接着3和5⽐较,5⼤,后移⼀位只到前⾯没有数了,或者前⾯的数⽐要插⼊的数⼩,就在对应的位置插⼊该数再对1执⾏以上步骤重复以上步骤,只到整个序列排序完成时间复杂度:O(n^2)空间复杂度:O(1)代码1class InsertionSort {2public:3int* insertionSort(int* A, int n)4 {5// write code here6int temp;7for(int i = 1; i < n; i ++)8 {9 temp = A[i];10for(int j = i - 1; j >= 0; j--)11 {12if(temp < A[j])13 {14 A[j + 1] = A[j];15if(j == 0)16 {17 A[j] = temp;18 }19 }20else21 {22 A[j + 1] = temp;23break;24 }25 }26 }27return A;28 }29 };四,归并排序思想:对数组中每个数看成是长度为1的有序区间,接着合并相邻两个长度为1的有序区间,变为长度为2的有序区间,接着合并相邻长度为2的有序区间变成长度为4的有序区间,依次进⾏,只到排序完成⽰意图:⾸先为长度为1的有序区间合并为长度为2的有序区间合并为长度为4的有序区间合并为长度为8的有序区间,排序完成时间复杂度:O(nlogn)空间复杂度:O(N)代码1class MergeSort {2public:3int* mergeSort(int* A, int n)4 {5 mergeSort(A,0,n-1);6return A;78 }9void mergeSort(int* A, int left, int right)10 {11if(left == right)12return;13int mid=(left+right)/2;14 mergeSort(A,left,mid);15 mergeSort(A,mid+1,right);16 merge_p(A,left,mid,right);17return;18 }1920void merge_p(int* A, int left, int mid, int right)21 {22int* temp = new int[right - left + 1];23int l = left;24int r = mid + 1;25int k = 0;26while(l <= mid && r <= right)27 {28if(A[l] < A[r])29 temp[k++] = A[l++];30else31 temp[k++] = A[r++];32 }33while(l <= mid)34 temp[k++] = A[l++];35while(r <= right)36 temp[k++] = A[r++];37for(int i = 0; i < k; i++)38 {39 A[left + i] = temp[i];40 }41 }4243 };五,快速排序思想:随机选择数组中的数,⼩于等于这个数的放在左边,⼤于这个数的放在右边,递归调⽤以上步骤,完成排序⽰意图:⾸先随机选择,划分区间递归调⽤,即可完成排序。

数据结构十大经典排序算法

数据结构十大经典排序算法

数据结构十大经典排序算法数据结构中的十大经典排序算法包括:1.冒泡排序(Bubble Sort):比较相邻两个元素,如果逆序则交换,重复多轮,直到无逆序情况。

2.插入排序(Insertion Sort):从第二个元素开始,将每个元素插入到已排序序列中的合适位置,重复多轮,直到所有元素有序。

3.归并排序(Merge Sort):将待排序序列分成若干子序列,对每个子序列进行归并排序,将有序的子序列合并成一个有序序列,重复多轮,直到所有元素有序。

4.堆排序(Heap Sort):将待排序序列构造成一个大根堆,将堆顶元素(最大值)与末尾元素交换,重复多轮,直到所有元素有序。

5.计数排序(Counting Sort):根据待排序序列中每个元素出现的次数,计算小于等于每个元素的元素个数,从后往前遍历待排序序列,将每个元素放在相应位置,重复一轮,直到所有元素有序。

6.选择排序(Selection Sort):首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,放到已排序序列的末尾(即与未排序序列的第一个交换)。

7.快速排序(Quick Sort):选择一个基准元素,通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小。

8.希尔排序(Shell Sort):先将整个待排序的记录序列分割成若干个子序列(由相隔某个“间隔”的记录组成的)分别进行直接插入排序,然后依次缩减间隔再进行排序。

9.基数排序(Radix Sort):通过多次分配基数对每一位进行比较和分配。

10.桶排序(Bucket Sort):利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。

这些算法各有优缺点,不同场景下应选择不同的算法来实现排序。

数据结构--排序算法总结

数据结构--排序算法总结

数据结构--排序算法总结概述排序的分类:内部排序和外部排序内部排序:数据记录在内存中进行排序外部排序:因排序的数据量大,需要内存和外存结合使用进行排序这里总结的八大排序是属于内部排序:当n比较大的时候,应采用时间复杂度为(nlog2n)的排序算法:快速排序、堆排序或归并排序。

其中,快速排序是目前基于比较的内部排序中被认为最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短。

———————————————————————————————————————————————————————————————————————插入排序——直接插入排序(Straight Insertion Sort)基本思想:将一个记录插入到已排序好的有序表中,从而得到一个新的,记录数增1的有序表。

即:先将序列的第1个记录看成一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止。

要点:设立哨兵,用于临时存储和判断数组边界直接插入排序示例:插入排序是稳定的,因为如果一个带插入的元素和已插入元素相等,那么待插入元素将放在相等元素的后边,所以,相等元素的前后顺序没有改变。

算法实现:[cpp]view plain copy1.#include<iostream>ing namespace std;3.4.void print(int a[], int n ,int i)5.{6. cout<<i<<":";7.for(int j= 0; j<8; j++){8. cout<<a[j] <<" ";9. }10. cout<<endl;11.}12.13.void InsertSort(int a[],int n)14.{15.int i,j,tmp;16.for(i=1;i<n;++i)17. {18.// 如果第i个元素大于第i-1个元素,直接插入19.// 否则20.// 小于的话,移动有序表后插入21.if(a[i]<a[i-1])22. {23. j=i-1;24. tmp=a[i]; // 复制哨兵,即存储待排序元素25. a[i]=a[i-1]; // 先后移一个元素26.while(tmp<a[j])27. {28.// 哨兵元素比插入点元素小,后移一个元素29. a[j+1]=a[j];30. --j;31. }32. a[j+1]=tmp; // 插入到正确的位置33. }34. print(a,n,i); // 打印每一趟排序的结果35. }36.}37.38.int main()39.{40.int a[8]={3,1,5,7,3,4,8,2};41. print(a,8,0); // 打印原始序列42. InsertSort(a,8);43.return 0;44.}分析:时间复杂度:O(n^2)———————————————————————————————————————————————————————————————————————插入排序——希尔排序(Shell Sort)基本思想:先将整个待排序的记录序列分割成为若干子序列,分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录依次进行直接插入排序。

十大排序算法总结

十大排序算法总结

十大排序算法总结在计算机科学领域,排序算法是一个非常重要的研究方向。

排序算法可以帮助我们更快速、更有效率地处理大量数据。

在本文中,我们将介绍十大常见的排序算法,包括冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序、基数排序。

1. 冒泡排序冒泡排序是一种基本的排序算法。

它重复地遍历待排序的序列,一次比较两个元素,如果它们的顺序错误就交换位置,直到整个序列有序为止。

冒泡排序的时间复杂度为O(n^2),空间复杂度为O(1)。

2. 选择排序选择排序是一种简单直观的排序算法。

它的工作原理是:首先在未排序的序列中找到最小元素,然后将其放到序列的起始位置;接着从剩余未排序的元素中继续寻找最小的元素,然后放到已排序序列的末尾。

选择排序的时间复杂度为O(n^2),空间复杂度为O(1)。

3. 插入排序插入排序是一种基本的排序算法。

它的工作原理是:将一个元素插入到已经排好序的序列中,使得插入后的序列仍然有序。

插入排序的时间复杂度为O(n^2),空间复杂度为O(1)。

4. 希尔排序希尔排序是一种改进版的插入排序。

它通过比较距离较远的元素,可以快速地将大元素向右移动,从而减少后续排序的比较次数。

希尔排序的时间复杂度为O(nlogn),空间复杂度为O(1)。

5. 归并排序归并排序是一种分治算法。

它将待排序的序列分成若干个子序列,每个子序列都是有序的。

然后再将有序的子序列合并成最终的有序序列。

归并排序的时间复杂度为O(nlogn),空间复杂度为O(n)。

6. 快速排序快速排序是一种基于分治思想的排序算法。

它通过不断地将序列分成两个部分,将较小的元素移动到左边、较大的元素移动到右边,最终将整个序列排好序。

快速排序的时间复杂度为O(nlogn),空间复杂度为O(nlogn)。

7. 堆排序堆排序是一种基于堆的排序算法。

它将待排序的序列看成一棵完全二叉树,每个节点的值都不大于其父节点的值。

然后将最大值不断地从堆中取出,放到已排序序列的末尾。

程序员必知8大排序

程序员必知8大排序

程序员必知8大排序——转自CSDN博客每天都在叫嚣自己会什么技术,什么框架,可否意识到你每天都在被这些新名词、新技术所迷惑,.NET、XML等等技术固然诱人,可是如果自己的基础不扎实,就像是在云里雾里行走一样,只能看到眼前,不能看到更远的地方。

这些新鲜的技术掩盖了许多底层的原理,要想真正的学习技术还是走下云端,扎扎实实的把基础知识学好,有了这些基础,要掌握那些新技术也就很容易了。

要编写出优秀的代码同样要扎实的基础,如果排序和查找算法学的不好,怎么对程序的性能进行优化?废话不多说,本文要介绍的这些排序算法就是基础中的基础,程序员必知!1、直接插入排序(1)基本思想:在要排序的一组数中,假设前面(n-1) [n>=2] 个数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。

如此反复循环,直到全部排好顺序。

(2)实例2、希尔排序(也称最小增量排序)(1)基本思想:算法先将要排序的一组数按某个增量d(n/2,n为要排序数的个数)分成若干组,每组中记录的下标相差d.对每组中全部元素进行直接插入排序,然后再用一个较小的增量(d/2)对它进行分组,在每组中再进行直接插入排序。

当增量减到1时,进行直接插入排序后,排序完成。

(2)实例:3、简单选择排序(1)基本思想:在要排序的一组数中,选出最小的一个数与第一个位置的数交换;然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。

(2)实例:4、堆排序(1)基本思想:堆排序是一种树形选择排序,是对直接选择排序的有效改进。

堆的定义如下:具有n个元素的序列(h1,h2,...,hn),当且仅当满足(hi>=h2i,hi>=2i+1)或(hi<=h2i,hi<=2i+1)(i=1,2,...,n/2)时称之为堆。

在这里只讨论满足前者条件的堆。

由堆的定义可以看出,堆顶元素(即第一个元素)必为最大项(大顶堆)。

八种常见的排序算法

八种常见的排序算法

⼋种常见的排序算法插⼊排序1.直接插⼊排序原理:将数组分为⽆序区和有序区两个区,然后不断将⽆序区的第⼀个元素按⼤⼩顺序插⼊到有序区中去,最终将所有⽆序区元素都移动到有序区完成排序。

要点:设⽴哨兵,作为临时存储和判断数组边界之⽤。

实现:void InsertSort(Nodetype p[],int length){int i,j;//分别为有序区和⽆序区指针for(i=1;i<length;i++)//逐步扩⼤有序区{j=i+1;if(p[j]<p[i]){p[0]=p[j];//存储待排序元素while(p[0]<p[i])//查找在有序区中的插⼊位置,同时移动元素{p[i+1]=p[i];//移动i--;}p[i+1]=p[0];//将元素插⼊}i=j-1;//还原有序区指针}}2.希尔排序原理:⼜称增量缩⼩排序。

先将序列按增量划分为元素个数相同的若⼲组,使⽤直接插⼊排序法进⾏排序,然后不断缩⼩增量直⾄为1,最后使⽤直接插⼊排序完成排序。

要点:增量的选择以及排序最终以1为增量进⾏排序结束。

实现:void ShellSort(Nodetype p[],int d){while(d>=1)//直到增量缩⼩为1{Shell(p,d);d=d/2;//缩⼩增量}}void Shell(Nodetype p[],int d){int i,j;int length=strlen(p);for(i=d+1;i<length){if(p[i]<p[i-d]){p[0]=p[i];j=i-d;while(j>0&&p[j]>p[0]){p[j+d]=p[j];j=j-d;}p[j+d]=p[0];}}}交换排序1.冒泡排序原理:将序列划分为⽆序和有序区,不断通过交换较⼤元素⾄⽆序区尾完成排序。

要点:设计交换判断条件,提前结束以排好序的序列循环。

实现:void BubbleSort(Nodetype p[]){int i,j;int ischanged;//设计跳出条件for(j=n-1;j<0;j--){ischanged=0;for(i=0;i<j;i++){if(p[i]>p[i+1])//如果发现较重元素就向后移动{int temp=p[i];p[i]=p[i+1];p[i+1]=temp;ischanged=1;}}if(!ischanged)//若没有移动则说明序列已经有序,直接跳出break;}}2.快速排序原理:不断寻找⼀个序列的中点,然后对中点左右的序列递归的进⾏排序,直⾄全部序列排序完成,使⽤了分治的思想。

8种排序算法

8种排序算法

J=2(38) [38 49] 65 97 76 13 27 49
J=3(65) [38 49 65] 97 76 13 27 49
J=4(97) [38 49 65 97] 76 13 27 49
J=5(76) [38 49 65 76 97] 13 27 49
2. 堆的定义: N个元素的序列K1,K2,K3,...,Kn.称为堆,当且仅当该序列满足特性:
Ki≤K2i Ki ≤K2i+1(1≤ I≤ [N/2])
堆实质上是满足如下性质的完全二叉树:树中任一非叶子结点的关键字均大于等于其孩子结点的关键字。例如序列10,15,56,25,30,70就是一个堆,它对应的完全二叉树如上图所示。这种堆中根结点(称为堆顶)的关键字最小,我们把它称为小根堆。反之,若完全二叉树中任一非叶子结点的关键字均大于等于其孩子的关键字,则称之为大根堆。
(6)基数排序
基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序,最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。基数排序基于分别排序,分别收集,所以其是稳定的排序算法。
2. 排序过程:
【示例】:
初始关键字 [49 38 65 97 76 13 27 49]
第一趟排序后 13 [38 65 97 76 49 27 49]
第二趟排序后 13 27 [65 97 76 49 38 49]
第三趟排序后 13 27 38 [97 76 49 65 49]
其次,说一下稳定性的好处。排序算法如果是稳定的,那么从一个键上排序,然后再从另一个键上排序,第一个键排序的结果可以为第二个键排序所用。基数排序就是这样,先按低位排序,逐次按高位排序,低位相同的元素其顺序再高位也相同时是不会改变的。另外,如果排序算法稳定,对基于比较的排序算法而言,元素交换的次数可能会少一些(个人感觉,没有证实)。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

八大排序算法概述排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。

我们这里说说八大排序就是内部排序。

当n较大,则应采用时间复杂度为O(nlog2n)的排序方法:快速排序、堆排序或归并排序序。

快速排序:是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短;基本思想:将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表。

即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止。

要点:设立哨兵,作为临时存储和判断数组边界之用。

直接插入排序示例:如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。

所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。

算法的实现:[cpp]view plain copyprint?1.void print(int a[], int n ,int i){2. cout<<i <<":";3.for(int j= 0; j<8; j++){4. cout<<a[j] <<" ";5. }6. cout<<endl;7.}8.9.10.void InsertSort(int a[], int n)11.{12.for(int i= 1; i<n; i++){13.if(a[i] < a[i-1]){ //若第i个元素大于i-1元素,直接插入。

小于的话,移动有序表后插入14.int j= i-1;15.int x = a[i]; //复制为哨兵,即存储待排序元素16. a[i] = a[i-1]; //先后移一个元素17.while(x < a[j]){ //查找在有序表的插入位置18. a[j+1] = a[j];19. j--; //元素后移20. }21. a[j+1] = x; //插入到正确位置22. }23. print(a,n,i); //打印每趟排序的结果24. }25.26.}27.28.int main(){29.int a[8] = {3,1,5,7,2,4,9,6};30. InsertSort(a,8);31. print(a,8,8);32.}效率:时间复杂度:O(n^2).其他的插入排序有二分插入排序,2-路插入排序。

希尔排序是1959 年由D.L.Shell 提出来的,相对直接排序有较大的改进。

希尔排序又叫缩小增量排序基本思想:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。

操作方法:1. 选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;2. 按增量序列个数k,对序列进行k 趟排序;3. 每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。

仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

希尔排序的示例:算法实现:我们简单处理增量序列:增量序列d = {n/2 ,n/4, n/8 .....1} n为要排序数的个数即:先将要排序的一组记录按某个增量d(n/2,n为要排序数的个数)分成若干组子序列,每组中记录的下标相差d.对每组中全部元素进行直接插入排序,然后再用一个较小的增量(d/2)对它进行分组,在每组中再进行直接插入排序。

继续不断缩小增量直至为1,最后使用直接插入排序完成排序。

[cpp]view plain copyprint?1.void print(int a[], int n ,int i){2. cout<<i <<":";3.for(int j= 0; j<8; j++){4. cout<<a[j] <<" ";5. }6. cout<<endl;7.}8./**9. * 直接插入排序的一般形式10. *11. * @param int dk 缩小增量,如果是直接插入排序,dk=112. *13. */14.15.void ShellInsertSort(int a[], int n, int dk)16.{17.for(int i= dk; i<n; ++i){18.if(a[i] < a[i-dk]){ //若第i个元素大于i-1元素,直接插入。

小于的话,移动有序表后插入19.int j = i-dk;20.int x = a[i]; //复制为哨兵,即存储待排序元素21. a[i] = a[i-dk]; //首先后移一个元素22.while(x < a[j]){ //查找在有序表的插入位置23. a[j+dk] = a[j];24. j -= dk; //元素后移25. }26. a[j+dk] = x; //插入到正确位置27. }28. print(a, n,i );29. }30.31.}32.33./**34. * 先按增量d(n/2,n为要排序数的个数进行希尔排序35. *36. */37.void shellSort(int a[], int n){38.39.int dk = n/2;40.while( dk >= 1 ){41. ShellInsertSort(a, n, dk);42. dk = dk/2;43. }44.}45.int main(){46.int a[8] = {3,1,5,7,2,4,9,6};47.//ShellInsertSort(a,8,1); //直接插入排序48. shellSort(a,8); //希尔插入排序49. print(a,8,8);50.}希尔排序时效分析很难,关键码的比较次数与记录移动次数依赖于增量因子序列d的选取,特定情况下可以准确估算出关键码的比较次数和记录的移动次数。

目前还没有人给出选取最好的增量因子序列的方法。

增量因子序列可以有各种取法,有取奇数的,也有取质数的,但需要注意:增量因子中除1 外没有公因子,且最后一个增量因子必须为1。

希尔排序方法是一个不稳定的排序方法。

基本思想:在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换;然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后一个数)比较为止。

简单选择排序的示例:操作方法:第一趟,从n 个记录中找出关键码最小的记录与第一个记录交换;第二趟,从第二个记录开始的n-1 个记录中再选出关键码最小的记录与第二个记录交换;以此类推.....第i 趟,则从第i 个记录开始的n-i+1 个记录中选出关键码最小的记录与第i 个记录交换,直到整个序列按关键码有序。

算法实现:[cpp]view plain copyprint?1.void print(int a[], int n ,int i){2. cout<<"第"<<i+1 <<"趟 : ";3.for(int j= 0; j<8; j++){4. cout<<a[j] <<" ";5. }6. cout<<endl;7.}8./**9. * 数组的最小值10. *11. * @return int 数组的键值12. */13.int SelectMinKey(int a[], int n, int i)14.{15.int k = i;16.for(int j=i+1 ;j< n; ++j) {17.if(a[k] > a[j]) k = j;18. }19.return k;20.}21.22./**23. * 选择排序24. *25. */26.void selectSort(int a[], int n){27.int key, tmp;28.for(int i = 0; i< n; ++i) {29. key = SelectMinKey(a, n,i); //选择最小的元素30.if(key != i){31. tmp = a[i]; a[i] = a[key]; a[key] = tmp; //最小元素与第i位置元素互换32. }33. print(a, n , i);34. }35.}36.int main(){37.int a[8] = {3,1,5,7,2,4,9,6};38. cout<<"初始值:";39.for(int j= 0; j<8; j++){40. cout<<a[j] <<" ";41. }42. cout<<endl<<endl;43. selectSort(a, 8);44. print(a,8,8);45.}简单选择排序的改进——二元选择排序简单选择排序,每趟循环只能确定一个元素排序后的定位。

我们可以考虑改进为每趟循环确定两个元素(当前趟最大和最小记录)的位置,从而减少排序所需的循环次数。

改进后对n 个数据进行排序,最多只需进行[n/2]趟循环即可。

具体实现如下:[cpp]view plain copyprint?1.void SelectSort(int r[],int n) {2.int i ,j , min ,max, tmp;3.for (i=1 ;i <= n/2;i++) {4.// 做不超过n/2趟选择排序5. min = i; max = i ; //分别记录最大和最小关键字记录位置6.for (j= i+1; j<= n-i; j++) {7.if (r[j] > r[max]) {8. max = j ; continue ;9. }10.if (r[j]< r[min]) {11. min = j ;12. }13. }14.//该交换操作还可分情况讨论以提高效率15. tmp = r[i-1]; r[i-1] = r[min]; r[min] = tmp;16. tmp = r[n-i]; r[n-i] = r[max]; r[max] = tmp;17.18. }19.}堆排序是一种树形选择排序,是对直接选择排序的有效改进。

相关文档
最新文档