博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
内部排序
阅读量:4069 次
发布时间:2019-05-25

本文共 7532 字,大约阅读时间需要 25 分钟。

参考资料:

常用的内部排序方法有:交换排序(冒泡排序、快速排序)、选择排序(简单选择排序、堆排序)、插入排序(直接插入排序、希尔排序)、归并排序、基数排序(一关键字、多关键字)。

===========================================================

时间复杂度 

排序方法                 最好情况                最坏情况             平均情况              稳定性 

冒泡排序                   O(n)                      O(n2)                 O(n2)                 稳定

快速排序                   O(nlogn)               O(n2)                  O(nlogn)            不稳定

简单选择排序                                                                   O(n2)               不稳定

堆排序                                                O(nlogn)                                      不稳定

直接插入排序            O(n)                      O(n2)                  O(n2)                  稳定

希尔排序                                                                       O(n1.3)              不稳定

归并排序                    O(nlogn)               O(nlogn)             O(nlogn)               稳定

基数排序                                                                       O(d(r+n))              稳定

=================================================================== 

冒泡排序:

1.基本思想:

两两比较待排序数据元素的大小,发现两个数据元素的次序相反时即进行交换,直到没有反序的数据元素为止。

2.排序过程:

设想被排序的数组R[1..N]垂直竖立,将每个数据元素看作有重量的气泡,根据轻气泡不能在重气泡之下的原则,从下往上扫描数组R,凡扫描到违反本原则的轻气泡,就使其向上"漂浮",如此反复进行,直至最后任何两个气泡都是轻者在上,重者在下为止。

不多说了,上代码: 

01 #include <iostream>
02  
03 using namespace std;
04  
05 void swap(int &a,int &b){
06     int temp = a;
07     a = b;
08     b = temp;
09 }
10  
11 void popSort(int *index,int len){
12     if(len <= 1){
13         return;
14     }
15     for(int i = 0 ; i < len ; ++i){
16         bool flag = false;
17         for(int j = 1 ; j < len - i ; ++j){
18             if(index[j-1] > index[j]){
19                 swap(index[j-1],index[j]);
20                 flag = true;
21             }
22         }
23         if(!flag){
24             return;
25         }
26     }
27 }
28  
29 int main()
30 {
31     int index[] = {1,2,3,4,5,6,7,8,9,0};
32     popSort(index,sizeof(index)/sizeof(int));
33     for(int i = 0 ;i < 10 ; ++i){
34         cout << index[i] << " ";
35     }
36     cout << endl;
37     return 1;
38 }

快速排序:

1.基本思想:

在 当前无序区R[1..H]中任取一个数据元素作为比较的"基准"(不妨记为X),用此基准将当前无序区划分为左右两个较小的无序区:R[1..I-1]和 R[I+1..H],且左边的无序子区中数据元素均小于等于基准元素,右边的无序子区中数据元素均大于等于基准元素,而基准X则位于最终排序的位置上,即 R[1..I-1]≤X.Key≤R[I+1..H](1≤I≤H),当R[1..I-1]和R[I+1..H]均非空时,分别对它们进行上述的划分过 程,直至所有无序子区中的数据元素均已排序为止。

    2.排序过程:

    【示例】:

    初始关键字 [49 38 65 97 76 13 27 49]

    第一次交换后 [27 38 65 97 76 13 49 49]

    第二次交换后 [27 38 49 97 76 13 65 49]

    J向左扫描,位置不变,第三次交换后 [27 38 13 97 76 49 65 49]

    I向右扫描,位置不变,第四次交换后 [27 38 13 49 76 97 65 49]

    J向左扫描 [27 38 13 49 76 97 65 49]

   (一次划分过程)

    初始关键字 [49 38 65 97 76 13 27 49]

    一趟排序之后 [27 38 13] 49 [76 97 65 49]

    二趟排序之后 [13] 27 [38] 49 [49 65]76 [97]

    三趟排序之后 13 27 38 49 49 [65]76 97

最后的排序结果 13 27 38 49 49 65 76 97

上代码: 
01 #include <iostream>
02  
03 using namespace std;
04  
05 void swap(int &a,int &b){
06     int temp = a;
07     a = b;
08     b = temp;
09 }
10  
11 int partition(int *index,int begin,int end){
12     int i = begin;
13     int j = end;
14      
15     while(i<j){
16         while(index[i]<=index[j]&&i<j){
17             --j;
18         }
19         if(i<j){
20             swap(index[i],index[j]);
21         }
22         while(index[i]<=index[j]&&i<j){
23             ++i;
24         }
25         if(i<j){
26             swap(index[i],index[j]);
27         }
28     }
29     return i;
30      
31 }
32  
33 void quickSort(int *index,int begin,int end){
34     if(begin>=end){
35         return;
36     }
37     int q = partition(index,begin,end);
38     quickSort(index,begin,q-1);
39     quickSort(index,q+1,end);
40 }
41  
42 int main()
43 {
44     int index[] = {2,6,2,3,6,7,8,3,1,2};
45     quickSort(index,0,9);
46     for(int i = 0 ;i < 10 ; ++i){
47         cout << index[i] << " ";
48     }
49     cout << endl;
50     return 1;
51 }

选择排序

 1.基本思想:

每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。

    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]

    第四趟排序后 13 27 38 49 [49 97 65 76]

    第五趟排序后 13 27 38 49 49 [97 97 76]

    第六趟排序后 13 27 38 49 49 76 [76 97]

    第七趟排序后 13 27 38 49 49 76 76 [ 97]

最后排序结果 13 27 38 49 49 76 76 97

上代码: 

01 #include <iostream>
02  
03 using namespace std;
04  
05 void swap(int &a,int &b){
06     int temp = a;
07     a = b;
08     b = temp;
09 }
10  
11 void selectSort(int *index,int len){
12     for(int i = 0 ; i < len ; ++i){
13         int pMin = i;
14         for(int j = i ; j < len ; ++j){
15             if(index[j]<index[pMin]){
16                 pMin = j;
17             }
18         }
19         if(pMin != i){
20             swap(index[i],index[pMin]);
21         }
22     }
23 }
24  
25 int main(){
26     int index[] = {2,6,2,3,6,7,8,3,1,2};
27     selectSort(index,sizeof(index)/sizeof(int));
28     for(int i = 0 ;i < 10 ; ++i){
29         cout << index[i] << " ";
30     }
31     cout << endl;
32     return 1;
33 }

堆排序

 1.基本思想:

    堆排序是一树形选择排序,在排序过程中,将R[1..N]看成是一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系来选择最小的元素。

    2.堆的定义: N个元素的序列K1,K2,K3,...,Kn.称为堆,当且仅当该序列满足特性:

        Ki≤K2i Ki ≤K2i+1(1≤ I≤ [N/2])

    堆实质上是满足如下性质的完全二叉树:树中任一非叶子结点的关键字均大于等于其孩子结点的关键字。例如序列10,15,56,25,30,70就是一个 堆,它对应的完全二叉树如上图所示。这种堆中根结点(称为堆顶)的关键字最小,我们把它称为小根堆。反之,若完全二叉树中任一非叶子结点的关键字均大于等 于其孩子的关键字,则称之为大根堆。

    3.排序过程:

    堆排序正是利用小根堆(或大根堆)来选取当前无序区中关键字小(或最大)的记录实现排序的。我们不妨利用大根堆来排序。每一趟排序的基本操作是:将当前无 序区调整为一个大根堆,选取关键字最大的堆顶记录,将它和无序区中的最后一个记录交换。这样,正好和直接选择排序相反,有序区是在原记录区的尾部形成并逐 步向前扩大到整个记录区。

【示例】:对关键字序列42,13,91,23,24,16,05,88建堆

上代码: 

01 #include <iostream>
02  
03 using namespace std;
04  
05 void swap(int &a,int &b){
06     int temp = a;
07     a = b;
08     b = temp;
09 }
10  
11 //堆中的元素在数组中从索引1开始,索引0中存储的是
12 //堆中当前的元素个数。
13 void heapAdjust(int *index,int pIndex,int end){
14     for(int j = 2*pIndex ; j <= end ; j = 2*pIndex){
15         if(j<end && index[j]<index[j+1]){
16             ++j;
17         }
18         if(index[pIndex]>=index[j]){
19             break;
20         }
21         swap(index[pIndex],index[j]);
22         pIndex = j;
23     }
24      
25 }
26  
27 void heapSort(int *index,int len){
28     for(int i = len/2 ; i > 0 ; --i){
29         heapAdjust(index,i,len);
30     }
31     for(int i = len ; i > 1 ; --i){
32         swap(index[1],index[i]);
33         heapAdjust(index,1,i-1);
34     }
35 }
36  
37 int main(){
38     int index[] = {10,2,6,2,3,6,7,8,3,1,2};//10表示有十个元素
39     heapSort(index,sizeof(index)/sizeof(int)-1);
40     for(int i = 1 ;i <= 10 ; ++i){
41         cout << index[i] << " ";
42     }
43     cout << endl;
44     return 1;
45 }
直接插入排序

1. 基本思想:

每次将一个待排序的数据元素,插入到前面已经排好序的数列中的适当位置,使数列依然有序;直到待排序数据元素全部插入完为止。

2. 排序过程:

【示例】:

[初始关键字] [49] 38 65 97 76 13 27 49

     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

     J=6(13) [13 38 49 65 76 97] 27 49

     J=7(27) [13 27 38 49 65 76 97] 49

     J=8(49) [13 27 38 49 49 65 76 97]

代码: 

01 #include <iostream>
02  
03 using namespace std;
04  
05 void swap(int &a,int &b){
06     int temp = a;
07     a = b;
08     b = temp;
09 }
10  
11 void insertSort(int *index,int len){
12     if(len <= 1){
13         return;
14     }
15     for(int i = 1 ; i < len ; ++i){
16         int temp = index[i];
17         int j = i-1;
18         for(;j>=0 && temp<index[j];--j){
19             index[j+1] = index[j];
20         }
21         index[j+1] = temp;
22     }
23 }
24  
25 int main(){
26     int index[] = {2,6,2,3,6,7,8,3,1,2};
27     insertSort(index,sizeof(index)/sizeof(int));
28     for(int i = 0 ;i < 10 ; ++i){
29         cout << index[i] << " ";
30     }
31     cout << endl;
32     return 1;
33 }
归并排序

1.排序思想:

设两个有序的子文件(相当于输入堆)放在同一向量中相邻的位置上:R[low..m],R[m+1..high],先将它们合并到一个局部的暂存向量R1(相当于输出堆)中,待合并完成后将R1复制回R[low..high]中。

       2.排序过程:

【示例】:

初始关键字    [46][38][56][30][88][80][38]

第一趟归并后[38 46][30 56][80 88][38]

第二趟归并后[30 38 46 56][38 80 88]

最终归并结果[30 38 38 46 56 80 88]

代码: 

01 #include <iostream>
02  
03 using namespace std;
04  
05 //index为合并后的队列,
06 //indexA为合并数组A,lenA为其长度
07 //indexB为合并数组B,lenB为其长度
08 void merge(int *index,int *indexA,int lenA,int *indexB,int lenB){
09     int *left = new int[lenA];
10     int *right = new int[lenB];
11     int i=0,j=0,k=0;
12  
13     memcpy(left,indexA,lenA*sizeof(int));
14     memcpy(right,indexB,lenB*sizeof(int));
15  
16     for(k = 0;k<lenA+lenB;k++){
17         if(i<lenA && j<lenB && left[i]<right[j]){
18             index[k] = left[i];
19             i++;
20         }else if(i<lenA && j<lenB){
21             index[k] = right[j];
22             j++;
23         }else if(j<lenB && i==lenA){
24             index[k] = right[j];
25             j++;
26         }else if(j==lenB && i<lenA){
27             index[k] = left[i];
28             i++;
29         }
30     }
31  
32     delete[] left;
33     delete[] right;
34 }
35  
36 void mergeSort(int *index,int begin,int end){
37     if(begin>=end){
38         return;
39     }
40     int pMid = begin + ((end-begin)>>1);
41     mergeSort(index,begin,pMid);
42     mergeSort(index,pMid+1,end);
43     merge(&index[begin],&index[begin],pMid-begin+1,&index[pMid+1],end-pMid);
44  
45 }
46  
47 int main(){
48     int index[] = {2,6,2,3,6,7,8,3,1,2};
49     mergeSort(index,0,9);
50     for(int i = 0 ;i < 10 ; ++i){
51         cout << index[i] << " ";
52     }
53     cout << endl;
54     return 1;
55 }

转载地址:http://sgmji.baihongyu.com/

你可能感兴趣的文章
io口的作用
查看>>
IO口的作用
查看>>
UIView的使用setNeedsDisplay
查看>>
归档与解归档
查看>>
Window
查看>>
为什么button在设置标题时要用一个方法,而不像lable一样直接用一个属性
查看>>
字符串的截取
查看>>
2. Add Two Numbers
查看>>
17. Letter Combinations of a Phone Number (DFS, String)
查看>>
93. Restore IP Addresses (DFS, String)
查看>>
19. Remove Nth Node From End of List (双指针)
查看>>
49. Group Anagrams (String, Map)
查看>>
139. Word Break (DP)
查看>>
23. Merge k Sorted Lists (Divide and conquer, Linked List) 以及java匿名内部类
查看>>
Tensorflow入门资料
查看>>
剑指_用两个栈实现队列
查看>>
剑指_顺时针打印矩阵
查看>>
剑指_栈的压入弹出序列
查看>>
剑指_复杂链表的复制
查看>>
服务器普通用户(非管理员账户)在自己目录下安装TensorFlow
查看>>