标签:
算法大致流程:给定初始序列L,L从前往后依次取出一个数据,将其直接插入到有序序列中。
算法的复杂度分析:时间复杂度:最坏的情况下,每从无序序列中取一个元素,就要遍历一遍有序序列,复杂度为O(n2);最好的情况下,每从无序序列中取出一个元素,直接放在了有序序列的后面,也就是不用遍历有序序列,此时,复杂度为O(n)。所以,平均复杂度为O(n2)。
空间复杂度:O(1)
1 #include<cstdio> 2 #define MAXSIZE 100 3 void out(int number[],int n) 4 { 5 for(int i=0; i<n; ++i) 6 printf("%d\t",number[i]); 7 } 8 void InsertSort(int number[],int n) 9 { 10 int i,j; 11 int temp,flag=0; 12 for(i=1; i<n; ++i) 13 { 14 flag=0; 15 temp=number[i]; 16 for(j=0; j<i; ++j) 17 { 18 if(number[i]<number[j]) 19 { 20 for(int k=i; k>j; --k) 21 number[k]=number[k-1]; 22 number[j]=temp; 23 flag=1; 24 } 25 if(flag==1) 26 break; 27 } 28 } 29 out(number,n); 30 } 31 32 int main() 33 { 34 int number[MAXSIZE]; 35 int n; 36 scanf("%d",&n); 37 for(int i=0; i<n; ++i) 38 scanf("%d",&number[i]); 39 InsertSort(number,n); 40 return 0; 41 }
算法大致流程:给定初始序列L,L从前往后依次取出一个数据,将其插入到有序序列中,到这里和直接插入排序相同。不同之处就在于,插入到有序序列中时,由于其是有序的,我们就可以采用二分的方式快速找到该元素在有序序列中的位置。
算法的复杂度分析:时间复杂度:最坏的情况下,每从无序序列中取一个元素,就要遍历n/2个有序序列元素,复杂度为O(n2),最好的情况和直接插入排序一样,也是O(n)。平均复杂度为:O(n2)。
空间复杂度:O(1)
算法大致流程:给定初始序列L,假设下标为0、1、2、3……n,例如,首先以5为增量分割序列,所以,0、5、10、15……为一组;1、6、11、16……为一组;2、7、12、17……为一组,将数列分为5组,这五组序列分别进行排序,构成一趟希尔排序。然后对排序后的整个数列,以3为增量分割序列,所以,0、3、6、9……一组;1、4、7、……一组,2、5、8、……一组,分为3组,对这三组数据分别进行排序,又做了一趟希尔排序。最后直到增量为1,就相当于整个序列作为一组进行一趟排序,从而使最终序列有序。
注:对于增量的选择,增量序列中没有除1以外的公因子,例如5、3、1就符合,8、4、2、1有公因子2,不符合。
算法的复杂度分析:时间复杂度:O(nlog2n)
空间复杂度:O(1)
算法大致流程:给定初始序列L(含有n个元素),先用第0个元素和第1个元素比较,如果第0个元素比第1个元素大,则两个元素交换,否则什么都不做,然后第1个元素和2个元素比较,如果第1个元素大,则交换,一直进行下去,直到比较到n-2和n-1,完成一趟冒泡,最大的元素a被就冒上来,放在了正确的位置上(即最大的放在了最后)。然后采用相同的方法完成第二次冒泡,直到比较到n-3和n-2,那么除了a意外的其他所有元素的最大值最终放在了n-2的位置上……最后,只剩2个元素时,比较,交换,算法完成。在一趟冒泡过程中,没有元素交换,也结束算法。
算法的复杂度分析:时间复杂度:最坏情况下,每次都要交换,复杂度为O(n2),最好的情况是已经有序,复杂度为O(n)。平均复杂度为:O(n2)。
空间复杂度:O(1)
1 #include <stdio.h> 2 3 void swap(int *a,int *b) 4 { 5 int temp; 6 temp=*a; 7 *a=*b; 8 *b=temp; 9 } 10 11 int main() 12 { 13 int i,j,n; 14 int number[100000]; 15 scanf("%d",&n); 16 for(int i=0;i<n;++i) 17 scanf("%d",&number[i]); 18 for(i=n-1;i>0;--i) 19 { 20 for(j=0;j<i;++j) 21 { 22 if(number[j]>number[j+1]) 23 { 24 swap(&number[j],&number[j+1]); 25 } 26 } 27 } 28 for(i=0;i<n;++i) 29 { 30 printf("%d ",number[i]); 31 } 32 return 0; 33 }
算法的大致流程:给定初始序列L,任意选定某个数作为基准(一般选择序列的第一个数L[0]),从L[1]开始向右依次比较,第一次发现某个数L[k]比基准大的时候,交换L[0]和L[left],此时的位置记为“left=left+1”,然后再开始从右往左查看,L[n-1]、L[n-2]……,当发现第一个比L[0]小的L[right]时候,交换L[0]和L[right],此时记录位置为“right=right+1”,然后从L[left]开始向右看,重复上述过程,直到遇到比L[0]大的元素,记录位置,从L[right]开始向左看……直到left和right相遇,一趟快排完成,此时L[0]左边的元素均比L[0]小,L[0]右边的元素均比L[0]大。L[0]将L分成左右两部分,L和R。
对L和R分别执行和L一样的操作,直到最后分得的L和R中只有两个元素。
算法的复杂度分析:时间复杂度:最好的情况下是:O(nlog2n),最坏的情况下是O(n2),待排序列越接近无序,效率越高,越有序,效率越低,排序的趟数和初始序列有关。平均复杂度为O(nlog2n)。
空间复杂度:需要借助栈,O(log2n)
1 #include<stdio.h> 2 int n; 3 void quick_sort(int number[],int left,int right) 4 { 5 int a,b; 6 int start; 7 int temp; 8 if(left>=right) 9 { 10 return; 11 } 12 temp=left; 13 a=left; 14 b=right; 15 start=number[left]; 16 while(left<right) 17 { 18 19 while(number[right]>=start&&right>left) 20 { 21 right--; 22 } 23 number[temp]=number[right]; 24 temp=right; 25 while(number[left]<=start&&left<right) 26 { 27 left++; 28 } 29 number[temp]=number[left]; 30 temp=left; 31 } 32 number[temp]=start; 33 quick_sort(number,a,right-1); 34 quick_sort(number,left+1,b); 35 } 36 37 int main() 38 { 39 int i,j; 40 int number[100000]; 41 scanf("%d",&n); 42 for(int i=0;i<n;++i) 43 scanf("%d",&number[i]); 44 quick_sort(number,0,n-1); 45 for(int i=0; i<n; i++) 46 { 47 printf("%d ",number[i]); 48 } 49 return 0; 50 }
算法大致流程:给定初始序列L(n个元素),从L中选择最小的值,和第一个元素交换,完成一次选择,此时有序序列的元素个数为1,无序序列的元素个数为n-1。接着对无序序列做相同的操作……直到无序序列个数为0,算法结束。
算法的复杂度分析:时间复杂度:平均复杂度为O(n2)。
空间复杂度:O(1)
1 #include<stdio.h> 2 void swap(int *a,int *b) 3 { 4 int temp; 5 temp=*a; 6 *a=*b; 7 *b=temp; 8 } 9 10 int main() 11 { 12 int i,j,n; 13 int number[1000]; 14 int point; 15 scanf("%d",&n); 16 for(i=0;i<n;i++) 17 { 18 scanf("%d",&number[i]); 19 } 20 21 for(i=0;i<n;i++) 22 { 23 int min=100000; 24 for(j=i;j<n;j++) 25 { 26 if(number[j]<=min) 27 { 28 min=number[j]; 29 point=j; 30 } 31 } 32 swap(&number[point],&number[i]); 33 } 34 35 for(i=0;i<n;i++) 36 { 37 printf("%d ",number[i]); 38 } 39 return 0; 40 }
堆:可看做一棵完全二叉树,对于每个非叶节点,满足父亲比孩子小(最小堆)或者父亲比孩子大(最大堆)。
算法大致流程:首先,用初始序列构建一棵完全二叉树,从最后一个非叶节点往前依次调整——比较他和它两个孩子的大小关系,若比两个孩子小,则将该父节点和两个孩子中较大的交换,即构建最大堆。
建立好最大堆时,第一趟排序完成,此时堆顶元素为最大元素,将他和最后一个元素交换,剩下的元素还是一棵完全二叉树,但是可能不满足堆的定义,将其重新构建为最大堆,(此时不满足最大堆的元素只有交换的那个值,所以,只需要调整那个值就可以了),将堆顶元素和最后一个元素交换,将剩下的元素构建最大堆,直到剩余元素只有1个,算法结束。
算法的复杂度分析:时间复杂度:最好和最坏的情况下复杂度均为O(nlog2n)。
空间复杂度:O(1)
算法的大致流程:首先将初始序列L中每个元素作为一组,共分为n组。n组中相邻的两两归并,形成n/2(向上取整)组,将这些组内的元素进行排序,然后将这n/2(向上取整)组元素再两两归并,形成n/4(向上取整)组,将组内元素排序……重复这个操作,直到n/2k=1,即最后归并为整个序列L,使之有序,算法结束。
算法的复杂度分析:时间复杂度:和初始序列无关,最好和最坏的情况下复杂度均为O(nlog2n)。
空间复杂度:需要转存序列,空间复杂度为O(n)
算法大致流程:基数排序就是按多个关键字进行排序,这里举两个栗子:
1、扑克牌(除大小王)排序:按照两个关键字:花色和数字。先按花色将牌分为4堆,然后将这4堆牌分别按照数字大小排序,最终使整副牌有序。
2、数字排序:按照低位优先的顺序,分别进行“分配”和“收集”操作,从低位到高位所有位都比完之后,算法完成,整个序列有序。
例如:对278、109、063、930、589、184、505、269、008、083进行基数排序。
首先,纵观全部的数字,0~9都有,那么我们就设置10和桶来接收这些位。
(1)先从最低位(个位)开始,即按照个位数进行分配,其余先不管,分配结果如下:
桶 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
元素 | 930 |
063 083 |
184 | 505 |
278 008 |
109 589 269 |
收集的时候,每个桶看成队列,执行“先进先出”,所以收集结果为“930、063、083、184、505、278、008、109、589、269”
(2)按照十位分配,结果如下:
桶 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
元素 |
505 008 109 |
930 |
063 269 |
278 |
083 184 589 |
收集:“505、008、109、930、063、269、278、083、184、589”
(3)按照百位进行分配,结果如下:
桶 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
元素 |
008 063 083 |
109 184 |
269 278 |
505 589 |
930 |
收集结果:“008、063、083、109、184、269、278、505、589、930”
至此,所有的位都比较完,算法结束,可见,最后的序列就是从小到大有序的。
该算法的思想就是,每次比较某一位时,“分配”的目的是保证下一位小的在前面,“收集”的目的是保证,该为小的在前面,这样,所有的收集分配结束后,小的在前面,大的在后面。
算法的复杂度分析:时间复杂度:平均和最坏的情况下复杂度均为O(d*(n+rd))。其中,d为关键字位数,栗子中d=3。n为元素数,栗子中,n=10。rd关键字取值范围,栗子中rd=10(即0~9)。
空间复杂度:需要rd个桶,空间复杂度为O(rd)。
标签:
原文地址:http://www.cnblogs.com/wktwj/p/4914718.html