排序算法-归并排序

妖狐艹你老母 2022-08-01 03:14 415阅读 0赞

归并排序也是一个比较快速的排序算法,其思想是运用分治的思想,先对要排序的数进行分,每次从中间分成两部分,然后知道分成最小,然后在把他们合起来,边合起来边排序,最后有序,每次分的复杂度是log(n),然后合起来变成有序的复杂度O(n),总的复杂度O(n*logn),速度比较快,但是每次合并要占用额外O(n)的空间,如果用链表实现的话可以避免,同时归并排序可用来求逆序对。

比如给这样一组数
3 5 2 10 4 6 7
首先分 3 5 2 | 10 4 6 7
继续分 3 | 5 2 | 10 4 | 6 7
继续分 3 | 5 | 2 | 10 | 4 | 7
然后开始合并,并排序
第一次:3 | 2 5 | 4 10 | 6 7
第二次: 2 3 5 | 4 6 7 10
第三次:2 3 4 5 6 7 10

数组实现的版本:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <vector>
  4. using namespace std;
  5. const int N = 1001000;
  6. int a[N];
  7. int b[N];
  8. void Merge(int l,int r)
  9. {
  10. if((r-l)==1 || l==r)
  11. return ;
  12. int mid = (l+r)/2;
  13. Merge(l,mid);
  14. Merge(mid,r);
  15. vector<int> tmp;
  16. int i = l,j = mid,cnt = 0;
  17. while(i<mid && j<r)
  18. {
  19. if(a[i]<=a[j])
  20. {
  21. b[cnt++] = (a[i]);
  22. i++;
  23. }
  24. else
  25. {
  26. b[cnt++] = (a[j]);
  27. j++;
  28. }
  29. }
  30. while(i<mid)
  31. {
  32. b[cnt++] = (a[i]);
  33. i++;
  34. }
  35. while(j<r)
  36. {
  37. b[cnt++] = (a[j]);
  38. j++;
  39. }
  40. for(int i=0;i<cnt;i++)
  41. {
  42. a[l+i] = b[i];
  43. }
  44. }
  45. int main()
  46. {
  47. //freopen("Input.txt","r",stdin);
  48. int n,k;
  49. while(~scanf("%d%d",&n,&k))
  50. {
  51. for(int i=0;i<n;i++)
  52. scanf("%d",&a[i]);
  53. Merge(0,n);
  54. for(int i=0;i<n;i++)
  55. printf("%d ",a[i]);
  56. for(int i=n-1;i>=(n-k);i--)
  57. printf("%d%c",a[i],i==(n-k)?'\n':' ');
  58. }
  59. return 0;
  60. }

链表实现的版本,不需要额外的内存:(提交到hdoj上面超时了,不知道为什么会慢)

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <vector>
  4. using namespace std;
  5. struct ListNode
  6. {
  7. int val;
  8. ListNode *next;
  9. };
  10. ListNode *Creat(int n)
  11. {
  12. ListNode *head = new ListNode;
  13. scanf("%d",&head->val);
  14. head->next = NULL;
  15. ListNode *p = head;
  16. n--;
  17. while(n--)
  18. {
  19. ListNode *tmp = new ListNode;
  20. scanf("%d",&tmp->val);
  21. tmp->next = NULL;
  22. p ->next = tmp;
  23. p = p->next;
  24. }
  25. return head;
  26. }
  27. int v[1010000];
  28. void print(ListNode *head)
  29. {
  30. int cnt = 0;
  31. while(head!=NULL)
  32. {
  33. v[cnt++] = (head->val);
  34. head = head->next;
  35. }
  36. }
  37. ListNode *Merge(ListNode *head)
  38. {
  39. if(head==NULL || head->next==NULL)
  40. return head;
  41. ListNode *fast = head,*flaw = head;
  42. while(fast->next!=NULL && fast->next->next!=NULL)
  43. {
  44. flaw = flaw->next;
  45. fast = fast->next;
  46. if(fast->next!=NULL)
  47. fast = fast->next;
  48. }
  49. fast = flaw->next;
  50. flaw->next = NULL;
  51. flaw = Merge(head); //SB
  52. fast = Merge(fast);
  53. ListNode *root = new ListNode;
  54. ListNode *p = root;
  55. while(flaw!=NULL && fast!=NULL)
  56. {
  57. if(flaw->val<=fast->val)
  58. {
  59. p->next = flaw;
  60. flaw = flaw->next;
  61. }
  62. else
  63. {
  64. p->next = fast;
  65. fast = fast->next;
  66. }
  67. p = p->next;
  68. }
  69. while(flaw!=NULL)
  70. {
  71. p->next = flaw;
  72. flaw = flaw->next;
  73. p = p->next;
  74. }
  75. while(fast!=NULL)
  76. {
  77. p->next = fast;
  78. fast = fast->next;
  79. p = p->next;
  80. }
  81. p = root->next;
  82. delete[] root;
  83. return p;
  84. }
  85. void dele(ListNode *head)
  86. {
  87. while(head!=NULL)
  88. {
  89. ListNode *tmp = head;
  90. head = head->next;
  91. delete[] tmp;
  92. }
  93. }
  94. int main()
  95. {
  96. // freopen("Input.txt","r",stdin);
  97. int n,k;
  98. while(~scanf("%d%d",&n,&k))
  99. {
  100. ListNode *head = Creat(n);
  101. head = Merge(head);
  102. print(head);
  103. dele(head);
  104. for(int i=n-1;i>=(n-k);i--)
  105. printf("%d%c",v[i],i==(n-k)?'\n':' ');
  106. }
  107. return 0;
  108. }

发表评论

表情:
评论列表 (有 0 条评论,415人围观)

还没有评论,来说两句吧...

相关阅读

    相关 排序算法——归并排序

    引言 归并排序可以使用递归或迭代的方式来实现,时间复杂度是都是 O(N \ logN)。 归并排序的核心是将待排序数组分组,可以整体二分,也可以设置步长迭代切分。归并排

    相关 排序算法-归并排序

    归并排序也是一个比较快速的排序算法,其思想是运用分治的思想,先对要排序的数进行分,每次从中间分成两部分,然后知道分成最小,然后在把他们合起来,边合起来边排序,最后有序,每次分的

    相关 排序算法——归并排序

    前言 将待排序序列R\[0...n-1\]看成是n个长度为1的有序序列,将相邻的有序表成对归并,得到n/2个长度为2的有序表;将这些有序序列再次归并,得到n/4个长度为4

    相关 排序算法归并排序

    一、前言     归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用 分治法(Divide and Conquer) 的一个非常典型的应用。 --------