算法(第四版)学习笔记——初级排序算法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法(第四版)学习笔记——初级排序算法相关的知识,希望对你有一定的参考价值。
时间复杂度(Time Complexity):
总运算次数表达式中受n的变化影响最大的那一项(不含系数)(注:若算法中语句执行次数为一个常数,则时间复杂度为O(1))
- 一个算法中的语句执行次数称为语句频度或时间频度。记为T(n)
空间复杂度(Space Complexity):
一个算法在运行过程中临时占用存储空间大小的量度(包括程序代码所占用的空间,输入数据所占用的空间和辅助变量所占用的空间这三个方面。)
注:
- 如当一个算法的空间复杂度为一个常量,即不随被处理数据量n的大小而改变时,可表示为O(1);
- 当一个算法的空间复杂度与以2为底的n的对数成正比时,可表示为0(log2n);
- 当一个算法的空I司复杂度与n成线性比例关系时,可表示为0(n).
冒泡排序
选择排序
步骤:(升序)
首先找到数组中最小的数,与数组第一位数交换位置(如果最小数是本身与本身交换)。接着在剩下的数中找第二小的数,与数组第二位数交换位置(如果第二小数是本身与本身交换)........按照相同步骤依次执行最后一个元素。
数据交换N次,数据比较(N-1)+(N-2)+........+3+2+1=N*(1+N-1)/2=N^2/2次(最后一个元素与自身交换)
时间复杂度:O(n2)
空间复杂度:O(1)
1 #include<stdio.h> 2 #include<malloc.h> 3 int main() 4 { 5 int n,i,j,min,temp; 6 scanf("%d",&n); 7 int *a=(int *)malloc(sizeof(int)*n); 8 for(i=0;i<n;i++) 9 scanf("%d",&a[i]); 10 for(i=0;i<n;i++) 11 { 12 min=a[i];//最小数 13 temp=i;//最小数在数组中的位置 14 for(j=i+1;j<n;j++) 15 { 16 if(min>a[j])//比较大小 17 { 18 min=a[j]; 19 temp=j; 20 } 21 } 22 a[temp]=a[i];//交换 23 a[i]=min; 24 } 25 for(i=0;i<n;i++) 26 printf("%d ",a[i]); 27 return 0; 28 }
- 运行时间与输入无关,有序数组输入其排序用时和相同长度的无序数组是一样的。
- 数据移动最少,每次只需移动两个数组
插入排序
直接插入排序
步骤:(升序)
将原数组分成两组,一组为已排好序的数组A,另一组为乱序数组B。数组A倒序(A[length-1])每个元素依次与数组B的一个元素比较(从B[0]开始),若A组某元素比B组元素大,A组元素后退一位为,B组元素腾出空间,然后B组推下一个元素.
时间复杂度:O(n2)
空间复杂度:O(1)
1 #include<stdio.h> 2 #include<malloc.h> 3 void sort(int *a,int n); 4 int main() 5 { 6 int n,i; 7 scanf("%d",&n); 8 int *a=(int *)malloc(sizeof(int )*n); 9 for(i=0;i<n;i++) 10 scanf("%d",&a[i]); 11 sort(a,n); 12 for(i=1;i<n;i++) 13 printf("%d ",a[i]); 15 return 0; 16 } 17 int less(int a,int b) 18 { 19 if(a<b) return 1; 20 return 0; 21 } 22 void sort(int *a,int n) 23 { 24 int i,j,temp,k; 25 for(i=1;i<n;i++) 26 { 27 temp=a[i]; 28 for(j=i-1;j>=0&&less(temp,a[j]);j--) 29 { 30 a[j+1]=a[j]; 31 } 32 a[j+1]=temp; 33 } 34 }
- 插入排序所需时间取决于输入元素的顺序
- 插入排序更适用于部分有序的数组,和小规模数组
希尔排序
步骤:(升序)
为加快速度的插入排序,交换不相邻的元素将数组部分变有序。使数组间隔h(h会改变)个元素有序。h在变化前,程序使h个元素间隔的小数组有序。
例:2—6—70(小数组每个元素间隔h个元素)..
时间复杂度:
空间复杂度:O(1)
#include<stdio.h> #include<malloc.h> //伸序 int less(int a[],int i,int j) { if(a[i]<a[j]) return 1; return 0; }
int main() { int n,h,i,j,temp,k; scanf("%d",&n); int *a=(int *)malloc(sizeof(int)*n); for(i=0;i<n;i++) scanf("%d",&a[i]); h=1; while(h<n/3) h=3*h+1; while(h>=1) { for(i=h;i<n;i++) { for(j=i;j>=h&&less(a,j,j-h);j-=h) { temp=a[j]; a[j]=a[j-h]; a[j-h]=temp; } } h/=3; } for(i=0;i<n;i++) printf("%d ",a[i]); return 0; }
疑问1:出现6—4—5这样的小数组,排序后还是为无序小数组?
答:并不会出现6—4—5这样的小数组,因为:
j=h 为 6—4小数组,会重新排序为有序4—6小数组
j=2h 为4—6—5小数组,会重新排序为有序4—5—6小数组
疑问2:如何选择h的递增数列?
书中用的的3*h+1与复杂递增序列的性能相近,但比较简单,所以书中将该递增数列提出作为参考
并未找到最优递增数列
优势:
希尔排序比插入排序和选择排序快得多,并且数组越大,优势越大。
参考资料:《算法第四版》
如何计算时间/空间复杂度:http://www.cnblogs.com/zakers/archive/2015/09/14/4808821.html
以上是关于算法(第四版)学习笔记——初级排序算法的主要内容,如果未能解决你的问题,请参考以下文章