快排与归并的算法(非递归版)

锦通  金牌会员 | 2024-6-13 19:53:05 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 670|帖子 670|积分 2010

一.快排
1.递归法(方法多样)
1>hoare版
注:该方法小编已经在上篇博客中先容过了,就不在这里过多赘述了,如果有兴趣的小伙伴可以看看小编的上篇博客哦
2>挖坑法
1)方法先容:界说最左边的数据为key,此时最左边的位置内可视为没有数据(即被挖了个坑),界说L,R两个下标,分别位于最左侧和最右侧,R向前走,若找到比key小的数据停下来,将该处数据放在坑位中,这时R指向的位置成为新坑;L开始向后走,若找到比key大的数据停下来,将该处数据放在坑位中,这时L指向的位置成为新坑;当R与L相遇时,将key放在相遇位置的坑中,此时完成依次排序,下面将数据分成[left,key-1],[key+1,right]两个区间举行下一轮的排序,直至排序完成
2)时间复杂度:O(N*logN)
     空间复杂度:O(1)
3)代码实现
  1. int qSortWay2(int* a, int left, int right)
  2. {
  3.         int key = a[left];
  4.         int begin = left, end = right;
  5.         while (begin < end)
  6.         {
  7.                 while (begin<end && a[end] > key)
  8.                 {
  9.                         end--;
  10.                 }
  11.                 a[begin] = a[end];
  12.                 while (begin<end && a[begin] < key)
  13.                 {
  14.                         begin++;
  15.                 }
  16.                 a[end] = a[begin];
  17.         }
  18.         a[begin] = key;
  19.     return begin;
  20. }
复制代码
3>前后指针法
1)方法先容:界说prev,cur两个下标,prev指向key所在位置,cur指向prev的下一个位置,cur向后走,如果找到比key小的数据,先将prev++,再将cur,prev所在位置的数据互换,cur继续向后找比key小的数据,直至cur越界访问数据,返回prev作为下次排序的分割点下标
2)时间复杂度:O(N*logN)
      空间复杂度:O(1)
3)代码实现
  1. int qSortWay3(int* a, int left, int right)
  2. {
  3.         int keyi = left;
  4.         int prev = left;
  5.         int cur = prev + 1;
  6.         while (cur <= right)
  7.         {
  8.                 if (a[cur] < a[keyi] && ++prev != cur)
  9.                         Swap(&a[cur], &a[prev]);
  10.                 cur++;
  11.         }
  12.         Swap(&a[prev], &a[keyi]);
  13.         return prev;
  14. }
复制代码
2.非递归法
1>方法先容:使用栈将每个区间的左右下标分别入栈,待数据被细分到只有左下标>=右下标时,开始将左右下标出栈,举行排序

2>使用非递归法可以大大低落栈的消耗,但不一定能进步服从
1)使用栈模拟递归法实现非递归排序雷同于二叉树的前序遍历
2)使用队列模拟递归法实现非递归排序雷同于二叉树的层序遍历(使用队列大概无法实现排序,且空间消耗很大,不推荐使用)
3>代码实现
  1. void QuickSortNonR(int* a, int left,int right)
  2. {
  3.         ST st;
  4.         STInit(&st);
  5.         STPush(&st, right);
  6.         STPush(&st, left);
  7.         while (!STEmpty(&st))
  8.         {
  9.                 int begin = STTop(&st);
  10.                 STPop(&st);
  11.                 int end = STTop(&st);
  12.                 STPop(&st);
  13.                 int keyi = qSortWay3(a, begin, end);
  14.                 //[begin,keyi-1],keyi,[keyi+1,end]
  15.                 if (keyi+1 < end)
  16.                 {
  17.                         STPush(&st, end);
  18.                         STPush(&st, keyi + 1);
  19.                 }
  20.                 if (begin < keyi - 1)
  21.                 {
  22.                         STPush(&st, keyi - 1);
  23.                         STPush(&st, begin);
  24.                 }
  25.         }
  26.         STDestory(&st);
  27. }
复制代码
二.归并(非递归法)
1.方法先容
1)使用gap对数据从小区间到大区间举行归并(雷同于将归并的递归方法用循环的方式举行从底层到顶层的排序),同时对两组数据[begin,begin+gap-1],[begin+gap,begin+2*gap-1]归并
2)gap从1开始,实现11归并,再2倍增长
3)注意此时存在越界访问的分风险,此时可以接纳如下方法举行避免越界

2.时间复杂度:O(N*logN)
    空间复杂度:O(N)
3.代码实现
  1. void MergeSortNonR(int* a, int n)
  2. {
  3.         int* tmp = (int*)malloc(sizeof(int) * n);
  4.         if (tmp == NULL)
  5.         {
  6.                 perror("malloc fail");
  7.                 return;
  8.         }
  9.        
  10.         int gap = 1;
  11.         while (gap < n)
  12.         {
  13.                 for (int i = 0; i < n; i += 2 * gap)
  14.                 {
  15.                         int begin1 = i, end1 = i + gap - 1;
  16.                         int begin2 = i + gap, end2 = i + 2 * gap - 1;
  17.                         int j = i;
  18.                         //前一组最后一个数据下标大于n-1,则后面一组数据全部越界
  19.                         if (end1 >= n)
  20.                         {
  21.                                 break;
  22.                         }
  23.                         //后一组最后一个数据下标大于n-1,则有部分数据越界,令尾巴等于n-1
  24.                         if (end2 >= n)
  25.                         {
  26.                                 end2 = n - 1;
  27.                         }
  28.                         while (begin1 <= end1 && begin2 <= end2)
  29.                         {
  30.                                 if (a[begin1] < a[begin2])
  31.                                 {
  32.                                         tmp[j++] = a[begin1++];
  33.                                 }
  34.                                 else
  35.                                 {
  36.                                         tmp[j++] = a[begin2++];
  37.                                 }
  38.                         }
  39.                         while (begin1 <= end1)
  40.                         {
  41.                                 tmp[j++] = a[begin1++];
  42.                         }
  43.                         while (begin2 <= end2)
  44.                         {
  45.                                 tmp[j++] = a[begin2++];
  46.                         }
  47.                         memcpy(a + i, tmp + i, sizeof(int) * (end2 - i + 1));
  48.                 }
  49.                 gap = gap * 2;
  50.         }
  51.        
  52.         free(tmp);
  53.         tmp = NULL;
  54. }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

锦通

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表