当前位置:   article > 正文

【C语言】插入类排序之直接插入排序、折半插入排序、希尔排序分析及输出每趟排序的结果_直接插入排序c语言代码

直接插入排序c语言代码

目录

直接插入排序

折半插入排序

希尔排序

完整代码


直接插入排序

        思想:将第i个记录插入到前i-1个已经排好的有序序列中,记录数组中arr[0]作为哨兵,存放当前待插入记录,防止越界以及被其他记录覆盖,首个记录arr[1]默认有序,将待插记录依次和前方记录对比,如果待插记录小于当前比较记录时,当前记录后移,直至大于等于当前比较记录时,插入其后即可,保持排序的稳定性。

  1. void InsertSort(int arr[],int length){//对待排序列arr进行直接插入排序
  2. for(int i=2;i<=length;i++){//将第i个记录插入前i-1个有序的序列中,arr[0]作哨兵,首个默认有序
  3. arr[0]=arr[i];//待插记录存入哨兵,防止越界以及被覆盖
  4. int j=i-1;
  5. while(arr[j]>arr[0]){//待插记录依次和前方记录比较调整,等于时不做调整保证稳点性
  6. arr[j+1]=arr[j];
  7. j--;
  8. }
  9. arr[j+1]=arr[0];
  10. printf("第%d次排序的结果为:\n",i-1);
  11. PrintArr(arr,length);
  12. }
  13. }

         时间复杂度:当待排记录已经从小到大顺序排列时为最好情况,此时每一趟仅需要比较1次,总共比较n-1次即可,不使用哨兵则不要移动,使用则每趟移动2次(arr[0]=arr[i]、arr[j+1]=arr[0])共移动2(n-1)次。最坏情况即待排记录从大到小逆序有序排列,第1躺比较2次,移动3次,第i躺比较i+1次,移动i+2次,总需要比较2+3+....+n=(n+2)(n-1)/2次,需要移动3+4+....+n+1=(n+4)(n-1)/2次,平均时间复杂度为T(n)=O(n^2)

折半插入排序

        思想:折半插入排序同直接插入排序一样,仅仅只是使用折半查找来确定待排序记录的插入位置,减少了关键字的比较次数,但是在找到后需要依次移动后续元素,未改善元素移动的次数。

  1. void BinSort(int arr[],int length){//折半插入排序
  2. for(int i=2;i<=length;i++){//折半插入排序即利用折半查找确定待插记录的位置在进行插入,优化了直接插入减少对比次数
  3. arr[0]=arr[i];//待插记录存入哨兵,防止越界以及被覆盖
  4. int low=1;
  5. int high=i-1;
  6. while(low<=high){//折半查找确定插入位置
  7. int mid=(low+high)/2;
  8. if(arr[0]>=arr[mid]){//等于时向右保证稳点性
  9. low=mid+1;
  10. }
  11. else{
  12. high=mid-1;
  13. }
  14. }
  15. for(int j=i-1;j>=low;j--){//当low>high时找到插入位置,元素依次后移
  16. arr[j+1]=arr[j];
  17. }
  18. arr[low]=arr[0];//插入待插记录
  19. printf("第%d次排序的结果为:\n",i-1);
  20. PrintArr(arr,length);
  21. }
  22. }

        时间复杂度:采用折半插入排序仅仅减少了关键字的比较次数,比较次数最大为折半判定树的深度即log2n+1,插入n个元素的平均比较次数为nlog2n,但并未改变移动次数,平均时间复杂度依然为T(n)=O(n^2)

希尔排序

        思想:根据规定的记录间隔d,将待排序列分隔为若干个子序列,对每个子序列都进行一次直接插入排序,排序后更新d的值为之前的一半直至d=1,再对最后基本有序的序列进行一次直接插入排序即可,一般设置d初始为记录数目的一半,直接插入排序可视为d=1的希尔排序。希尔排序不能保证稳定性例如:2,4,1,2

  1. void ShellSort(int arr[],int length){//希尔排序
  2. for(int d=length/2;d>=1;d=d/2){//根据设置的记录间距d分为若干子序列进行插入排序
  3. for(int i=d+1;i<=length;i++){//从当前子序列的第二个位置开始直接插入,并更换不同的子序列
  4. arr[0]=arr[i];//待插记录存入哨兵,防止越被覆盖
  5. int j=i-d;//与当前子序列的值比较
  6. while(arr[j]>arr[0]){
  7. arr[j+d]=arr[j];
  8. j-=d;//更新j为下一个子序列的值
  9. if(j<0){//越界判断
  10. break;
  11. }
  12. }
  13. arr[j+d]=arr[0];//插入待排记录
  14. }
  15. static int nums=1;
  16. printf("第%d次排序的结果为:\n",nums);
  17. PrintArr(arr,length);
  18. nums++;
  19. }
  20. }

         时间复杂度:尽管d=1时等同于直接插入排序但是此时待排序列已经基本有序,效率对于直接插入排序也有提升,一般认为时间复杂度为T(n)=O(n^1.5)。

完整代码

  1. #include<stdio.h>
  2. void InsertSort(int*,int);//直接插入排序
  3. void BinSort(int*,int);//折半插入排序
  4. void ShellSort(int*,int);//希尔排序
  5. void PrintArr(int*,int);//输出记录
  6. void InsertSort(int arr[],int length){//对待排序列arr进行直接插入排序
  7. for(int i=2;i<=length;i++){//将第i个记录插入前i-1个有序的序列中,arr[0]作哨兵,首个默认有序
  8. arr[0]=arr[i];//待插记录存入哨兵,防止越界以及被覆盖
  9. int j=i-1;
  10. while(arr[j]>arr[0]){//待插记录依次和前方记录比较调整,等于时不做调整保证稳点性
  11. arr[j+1]=arr[j];
  12. j--;
  13. }
  14. arr[j+1]=arr[0];
  15. printf("第%d次插入排序的结果为:\n",i-1);
  16. PrintArr(arr,length);
  17. }
  18. }
  19. void BinSort(int arr[],int length){//折半插入排序
  20. for(int i=2;i<=length;i++){//折半插入排序即利用折半查找确定待插记录的位置在进行插入,优化了直接插入减少对比次数
  21. arr[0]=arr[i];//待插记录存入哨兵,防止越界以及被覆盖
  22. int low=1;
  23. int high=i-1;
  24. while(low<=high){//折半查找确定插入位置
  25. int mid=(low+high)/2;
  26. if(arr[0]>=arr[mid]){//等于时向右保证稳点性
  27. low=mid+1;
  28. }
  29. else{
  30. high=mid-1;
  31. }
  32. }
  33. for(int j=i-1;j>=low;j--){//当low>high时找到插入位置,元素依次后移
  34. arr[j+1]=arr[j];
  35. }
  36. arr[low]=arr[0];//插入待插记录
  37. printf("第%d次折半排序的结果为:\n",i-1);
  38. PrintArr(arr,length);
  39. }
  40. }
  41. void ShellSort(int arr[],int length){//希尔排序
  42. for(int d=length/2;d>=1;d=d/2){//根据设置的记录间距d分为若干子序列进行插入排序
  43. for(int i=d+1;i<=length;i++){//从当前子序列的第二个位置开始直接插入,并更换不同的子序列
  44. arr[0]=arr[i];//待插记录存入哨兵,防止越被覆盖
  45. int j=i-d;//与当前子序列的值比较
  46. while(arr[j]>arr[0]){
  47. arr[j+d]=arr[j];
  48. j-=d;//更新j为下一个子序列的值
  49. if(j<0){//越界判断
  50. break;
  51. }
  52. }
  53. arr[j+d]=arr[0];//插入待排记录
  54. }
  55. static int nums=1;
  56. printf("第%d次希尔排序的结果为:\n",nums);
  57. PrintArr(arr,length);
  58. nums++;
  59. }
  60. }
  61. void PrintArr(int arr[],int length){//输出记录序列
  62. for(int i=1;i<=length;i++){
  63. printf("%d ",arr[i]);
  64. }
  65. printf("\n");
  66. }
  67. int main(){
  68. int arr[]={00,55,88,66,33,99,44,77,11,22};
  69. int length=sizeof(arr)/sizeof(arr[0])-1;
  70. printf("排序前为:\n");
  71. PrintArr(arr,length);
  72. // InsertSort(arr,length);//直接插入排序
  73. // BinSort(arr,length);//折半插入排序
  74. ShellSort(arr,length);//希尔排序
  75. printf("排序后为:\n");
  76. PrintArr(arr,length);
  77. return 0;
  78. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/码创造者/article/detail/821393
推荐阅读
相关标签
  

闽ICP备14008679号