排序算法
—学习小甲鱼的数据结构与算法笔记
将一组“无序”的记录序列调整为“有序”的记录序列
排序依据是关键字之间的大小关系,同一记录集合,针对不同的关键字进行排序,可以得到不用的序列
排序的稳定性
稳定排序 不稳定排序
内排序:外排序?
排序算法的性能: 时间性能 辅助空间 算法的复杂性
冒泡排序:
冒泡排序的基本思想: 相邻的两个元素记录的关键字,如果反序则交换,直到没有反序的记录位置。
如果有n个元素,需要比较n-1次,每一轮减少1次比较
### 从下往上(冒泡)
下面是两种冒泡排序,推荐第二种。(主要是从下往上,冒泡的感觉(其实主要是效率提高了不少))
1 #include <stdio.h> 2 3 int count1,count2; 4 //低端的冒泡排序 5 void BubbbleSort(int k[],int n){ 6 int i,j,tmp; 7 count1 = count2 = 0; 8 for ( i=0; i<n-1; i++ ){ 9 for ( j=i+1; j<n; j++ ){ 10 count1++; 11 if ( k[i] > k[j] ){ 12 count2++; 13 tmp = k[j]; 14 k[j] = k[i]; 15 k[i] = tmp; 16 }}}} 17 //改进后的冒泡排序 18 void BubbbleSort2(int k[],int n){ 19 int i,j,tmp,flag; 20 count1 = count2 = 0; 21 for ( i=0; i<n-1 && flag; i++ ){ 22 for ( j=n-1; j>i; j-- ){ 23 count1++; 24 flag = 0; 25 if ( k[j] < k[j-1] ){ 26 count2++; 27 tmp = k[j-1]; 28 k[j-1] = k[j]; 29 k[j] = tmp; 30 flag = 1; 31 }}}} 32 33 void display(int k[],int n){ 34 int i; 35 for ( i=0; i<n; i++) 36 printf("%d ",k[i]); 37 printf("总共进行了%d次比较,进行了%d次移动!\n",count1,count2); 38 } 39 40 void main() { 41 int a1[10] = {1,0,2,3,4,5,6,7,8,9}; 42 int a2[10] = {1,0,2,3,4,5,6,7,8,9}; 43 BubbbleSort(a1,10); 44 display(a1,10); 45 BubbbleSort2(a2,10); 46 display(a2,10); 47 }
输出结果:
0 1 2 3 4 5 6 7 8 9 总共进行了45次比较,进行了1次移动! 0 1 2 3 4 5 6 7 8 9 总共进行了17次比较,进行了1次移动!
大概是这样,所以良好的改进了冒泡排序:
选择排序
选择排序算法就是通过n-i次关键字之间比较,从n-i+1个记录中选出关键字最小的记录,并和第i (1<=i<=n) 个记录交换
1 #include <stdio.h> 2 3 void SelectSort(int k[],int n){ 4 int i,j,min,tmp; 5 int count1 = 0,count2 = 0; 6 for ( i=0; i<n-1; i++ ){ 7 min = i; 8 for ( j=i+1; j<n; j++ ){ 9 count1++; 10 if( k[j]< k[min] ){ 11 min = j; 12 }} 13 if ( min != i ){ 14 count2++; 15 tmp = k[min]; 16 k[min] = k[i]; 17 k[i] = tmp; 18 }}printf("总共进行了%d次比较,进行了%d次移动!\n",count1,count2);} 19 20 void display(int k[],int n){ 21 int i; 22 for ( i=0; i<n; i++) 23 printf("%d ",k[i]); 24 } 25 26 void main() { 27 int a[10] = {1,0,2,3,4,5,6,7,8,9}; 28 SelectSort(a,10); 29 display(a,10); 30 }
总共进行了45次比较,进行了1次移动! 0 1 2 3 4 5 6 7 8 9
如果跟没有优化过的冒泡排序相比:
选择排序似乎是有优势的。
直接插入排序
直接插入排序算法(Straight Insertion Sort)的基本操作是将一个记录插入到已经排好序的有序表中,从而得到新的、记录数增加1的有序表。
1 #include <stdio.h> 2 3 void InsertSort(int k[],int n){ 4 int i,j,tmp; 5 for ( i=1; i<n; i++ ) { 6 if( k[i]<k[i-1] ) { 7 tmp = k[i]; 8 for ( j=i-1; k[j]>tmp; j-- ) { 9 if(!j) 10 break; 11 k[j+1] = k[j]; 12 }k[j+1] = tmp; 13 }}} 14 //printf("总共进行了%d次比较,进行了%d次移动!\n",count1,count2); 15 16 void display(int k[],int n){ 17 int i; 18 for ( i=0; i<n; i++) 19 printf("%d ",k[i]); 20 } 21 22 void main() { 23 // int a[10] = {1,0,2,3,4,5,6,7,8,9}; 24 int a[10] = {5,2,6,0,3,9,1,7,4,8}; 25 InsertSort(a,10); 26 display(a,10); 27 }
希尔排序
时间复杂度 O(n*logn)
直接插入排序的改进版:
先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,
待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。
1 #include <stdio.h> 2 3 void ShellSort(int k[],int n){ 4 int i,j,tmp; 5 int gap = n; 6 do{ 7 gap = gap/3 + 1; 8 for ( i=gap; i<n; i++ ) { 9 if( k[i]<k[i-gap] ) { 10 tmp = k[i]; 11 for ( j=i-gap; k[j]>tmp; j-=gap ) { 12 k[j+gap] = k[j]; 13 }k[j+gap] = tmp; 14 }}}while(gap >1);} 15 16 void display(int k[],int n){ 17 int i; 18 for ( i=0; i<n; i++) 19 printf("%d ",k[i]); 20 } 21 22 int main() { 23 int a[10] = {5,2,6,0,3,9,1,7,4,8}; 24 ShellSort(a,10); 25 display(a,10); 26 27 return 0; 28 }