当前位置:   article > 正文

常见的排序算法原理及c代码实现_给定两组无序数列编程实现升序有序数列c语言

给定两组无序数列编程实现升序有序数列c语言

1.冒泡排序

原理:比较两个相邻的元素,将值大的元素交换到右边

依次比较相邻的两个数,将比较小的数放在前面,比较大的数放在后面。

    (1)第一次比较:首先比较第一和第二个数,将小数放在前面,将大数放在后面。

    (2)比较第2和第3个数,将小数 放在前面,大数放在后面。

    ......

    (3)如此继续,知道比较到最后的两个数,将小数放在前面,大数放在后面,重复步骤,直至全部排序完成

    (4)在上面一趟比较完成后,最后一个数一定是数组中最大的一个数,所以在比较第二趟的时候,最后一个数是不参加比较的。

    (5)在第二趟比较完成后,倒数第二个数也一定是数组中倒数第二大数,所以在第三趟的比较中,最后两个数是不参与比较的。

    (6)依次类推,每一趟比较次数减少依次

  1. void bubbleSort(int *arr,int n)
  2. {
  3. int m,i,j;
  4. for(i=0;i<n-1;i++)
  5. for(j=0;j<n-1-i;j++)
  6. if(arr[j]>arr[j+1])
  7. {
  8. m=arr[j];
  9. arr[j]=arr[j+1];
  10. arr[j+1]=m;
  11. }
  12. }

2.插入排序

原理:每一步将一个待排序的数据插入到前面已经排好序的有序序列中,直到插完所有元素为止。

算法实现:直接插入排序是将无序序列中的数据插入到有序的序列中,在遍历无序序列时,首先拿无序序列中的首元素去与有序序列中的每一个元素比较并插入到合适的位置,一直到无序序列中的所有元素插完为止。对于一个无序序列arr{4,6,8,5,9}来说,我们首先先确定首元素4是有序的,然后在无序序列中向右遍历,6大于4则它插入到4的后面,再继续遍历到8,8大于6则插入到6的后面,这样继续直到得到有序序列{4,5,6,8,9}。

  1. void StraightSort(int *arr,int len)
  2. {
  3. int tmp;
  4. int i;
  5. int j;
  6. for (i = 1;i < len;i++)
  7. {
  8. tmp = arr[i];
  9. for (j = i - 1;j >= 0 && arr[j] > tmp;j--)
  10. {
  11. arr[j + 1] = arr[j];
  12. }
  13. arr[j + 1] = tmp;
  14. }
  15. }

3.希尔排序

原理:希尔排序是插入排序的改进版,首先它把较大的数据集合分割成若干个小组(逻辑上分组),然后对每一个小组分别进行插入排序,此时,插入排序所作用的数据量比较小(每一个小组),插入的效率比较高。

图解算法---希尔排序

举例:按下标相隔距离为4分组,也就是说把下标相差4的分到一组,a[0]与a[4]是一组、a[1]与a[5]是一组...,这里的差值(距离)被称为增量

每个分组进行插入排序后,各个分组就变成了有序的了(整体不一定有序)

图解算法---希尔排序

然后缩小增量为上个增量的一半:2,继续划分分组,此时,每个分组元素个数多了,但是,数组变的部分有序了,插入排序效率同样比高

图解算法---希尔排序

同理对每个分组进行排序(插入排序),使其每个分组各自有序

图解算法---希尔排序

最后设置增量为上一个增量的一半:1,则整个数组被分为一组,此时,整个数组已经接近有序了,插入排序效率高

图解算法---希尔排序

同理,对这仅有的一组数据进行排序,排序完成

  1. void shell_sort(int array[], int length){
  2. int i;
  3. int j;
  4. int k;
  5. int gap; //gap是分组的步长
  6. int temp; //希尔排序是在直接插入排序的基础上实现的,所以仍然需要哨兵
  7. for(gap=length/2; gap>0; gap=gap/2){
  8. for(i=0; i<gap; i++){
  9. for(j=i+gap; j<length; j=j+gap){ //单独一次的插入排序
  10. if(array[j] < array[j - gap]){
  11. temp = array[j]; //哨兵
  12. k = j - gap;
  13. while(k>=0 && array[k]>temp){
  14. array[k + gap] = array[k];
  15. k = k - gap;
  16. }
  17. array[k + gap] = temp;
  18. }
  19. }
  20. }
  21. }

4.归并排序

原理:分治法。

  • 分解(Divide):将n个元素分成个含n/2个元素的子序列。
  • 解决(Conquer):用合并排序法对两个子序列递归的排序。
  • 合并(Combine):合并两个已排序的子序列已得到排序结果。

  

具体的我们以一组无序数列{14,12,15,13,11,16}为例分解说明,如下图所示:

上图中首先把一个未排序的序列从中间分割成2部分,再把2部分分成4部分,依次分割下去,直到分割成一个一个的数据,再把这些数据两两归并到一起,使之有序,不停的归并,最后成为一个排好序的序列。

  1. void merge_sort_recursive(int arr[], int reg[], int start, int end) {
  2. if (start >= end)
  3. return;
  4. int len = end - start, mid = (len >> 1) + start;
  5. int start1 = start, end1 = mid;
  6. int start2 = mid + 1, end2 = end;
  7. merge_sort_recursive(arr, reg, start1, end1);
  8. merge_sort_recursive(arr, reg, start2, end2);
  9. int k = start;
  10. while (start1 <= end1 && start2 <= end2)
  11. reg[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++];
  12. while (start1 <= end1)
  13. reg[k++] = arr[start1++];
  14. while (start2 <= end2)
  15. reg[k++] = arr[start2++];
  16. for (k = start; k <= end; k++)
  17. arr[k] = reg[k];
  18. }
  19. void merge_sort(int arr[], const int len) {
  20. int reg[len];
  21. merge_sort_recursive(arr, reg, 0, len - 1);
  22. }

5.快速排序

原理:分治法,选择一个基准数,通过一趟排序将要排序的数据分割成独立的两部分;其中一部分的所有数据都比另外一部分的所有数据都要小。然后,再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

下面以数列a={30,40,60,10,20,50}为例,演示它的快速排序过程(如下图)。

上图只是给出了第1趟快速排序的流程。在第1趟中,设置x=a[i],即x=30。
(01) 从"右 --> 左"查找小于x的数:找到满足条件的数a[j]=20,此时j=4;然后将a[j]赋值a[i],此时i=0;接着从左往右遍历。
(02) 从"左 --> 右"查找大于x的数:找到满足条件的数a[i]=40,此时i=1;然后将a[i]赋值a[j],此时j=4;接着从右往左遍历。
(03) 从"右 --> 左"查找小于x的数:找到满足条件的数a[j]=10,此时j=3;然后将a[j]赋值a[i],此时i=1;接着从左往右遍历。
(04) 从"左 --> 右"查找大于x的数:找到满足条件的数a[i]=60,此时i=2;然后将a[i]赋值a[j],此时j=3;接着从右往左遍历。
(05) 从"右 --> 左"查找小于x的数:没有找到满足条件的数。当i>=j时,停止查找;然后将x赋值给a[i]。此趟遍历结束!

按照同样的方法,对子数列进行递归遍历。最后得到有序数组!

  1. /*
  2. * 快速排序
  3. *
  4. * 参数说明:
  5. * a -- 待排序的数组
  6. * l -- 数组的左边界(例如,从起始位置开始排序,则l=0)
  7. * r -- 数组的右边界(例如,排序截至到数组末尾,则r=a.length-1)
  8. */
  9. void quick_sort(int a[], int l, int r)
  10. {
  11. if (l < r)
  12. {
  13. int i,j,x;
  14. i = l;
  15. j = r;
  16. x = a[i];
  17. while (i < j)
  18. {
  19. while(i < j && a[j] > x)
  20. j--; // 从右向左找第一个小于x的数
  21. if(i < j)
  22. a[i++] = a[j];
  23. while(i < j && a[i] < x)
  24. i++; // 从左向右找第一个大于x的数
  25. if(i < j)
  26. a[j--] = a[i];
  27. }
  28. a[i] = x;
  29. quick_sort(a, l, i-1); /* 递归调用 */
  30. quick_sort(a, i+1, r); /* 递归调用 */
  31. }
  32. }

 

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号