快速排序&&归并排序

来源:互联网 发布:plc编码器编程 编辑:程序博客网 时间:2024/06/05 03:50

前几天刚学了但是没做题实践一下,总体感觉就是分治,归并。有点搞不懂有什么太大区别。

今天做POJ2299,线段树的题,求逆序数,思路是用下标来记录然后求和,我超给了模版,不过不太清楚怎么用,关键是给了也不知道原理,哪一步是怎么做。

发现DISCUSS里方法众多,归并比较多,就百度归并模版后发现竟然就有这个类似的题(XMU1328 hdu3743),模版和AC代码就差一句话。

#include <stdio.h>    #include <stdlib.h>    #define MAXN 1000100    int input[MAXN] = {0};    int tmp[MAXN];     void merge(int left, int middle, int right)    {         int i, j, k;         i = left, j= middle+1, k = 1;         while(i<= middle && j <= right)         {                   if(input[j] < input[i])                   {                        tmp[k++] = input[j++];                   }                   else            {                        tmp[k++] = input[i++];            }         }         while(i <= middle)          tmp[k++] = input[i++];         while(j <= right)         tmp[k++] = input[j++];              for(i = left, k = 1; i<= right; i++, k++)                input[i] = tmp[k];    }    void merge_sort(int left, int right)    {         if(left < right)         {                 int middle = (left + right)/2;                 merge_sort(left, middle);                 merge_sort(middle+1, right);                 merge(left, middle, right);         }    }    int main(){        int n,i;        while( scanf("%d",&n)&&n)      {      for(i=0;i<n;++i)            scanf("%d",&input[i]);        merge_sort(0,n-1);        for(i=0;i<n-1;++i)            printf("%d ",input[i]);      printf("%d\n",input[i]);      }      return 0;    }     

以上是模版,而关键的一句话是 result += middle - i + 1;     

插入第十四行,为什么呢,分析一下题目数据

9 1 0 5 4

分割为9  1        ------0 5 4

最终是        9 -----1--------0--------5------4

归并19----------------045          这里+2

然后最终归并。放0,+2,放4,+1,放5,+1最终result=2+2+1+1=6。(第一次写分析性的,如果不对请指正)




附上归并和快排的图,比较好理解。



归并是分治到低进行合并,快排是分治和合并同时进行。然后一个注释比较清楚的快排模版

#include <iostream>    using namespace std;    template <class T>  void quick_sort(T* array,int low,int high)  {      if(low<high) //如果low==high,说明只有一个元素,不需要排序,即到了quick_sort返回的时候      {          int i = low;          int j = high;   //用i,j分别标示向前向后移动的游标          T temp = array[i];  //暂存标尺元素,最后再处理,这样可以在比较过程中直接覆盖,而不造成元素值的丢失          while(i<j)   //i>=j作为一趟快排结束的标志,i>=j后,所有大于temp的元素都已放在i的右边,所有小于temp的元素都已放在i的左边,i就是temp应该放的位置          {              while( j>i && array[j]>temp ) //用j自右向左找到第一个比temp小的元素,用它和temp所在位置做进行交换                  j--;              if(i==j)    //如果一直找到i还没找到,说明i右面的所有元素都比temp大,此次快排的任务完成                  break;              array[i] = array[j];    //交换操作              i++;              while( i<j && array[i]<=temp )    //用i自左向右找到第一个比temp大的元素,用它和temp所在位置做进行交换                  i++;              if(i==j)    //如果一直找到j还没找到,说明j左面的所有元素都比temp小,此次快排的任务完成                  break;              array[j] = array[i];    //交换操作              j--;          }          array[i] = temp;    //退出循环后的i时temp应该摆放的位置,因为i左面的元素都比temp小,右边都大,且i位置元素已被移到其他位置          quick_sort(array,low,i-1);  //递归调用quick_sort分别对i前和i后的子序列进行快排          quick_sort(array,i+1,high);      }  }    void quicksort(int* array,int low,int high)  {      if(low<high)      {          int i = low;          int j = high;          int temp = array[i];          while(i<j)          {              while( j>i && array[j]>temp )                  j--;              if(i==j)                  break;              array[i] = array[j];              i++;              while( i<j && array[i]<=temp )                  i++;              if(i==j)                  break;              array[j] = array[i];              j--;          }          array[i] = temp;          quicksort(array,low,i-1);          quicksort(array,i+1,high);      }  }    int main()  {      int number[30] = {23,3,26,24,5,1,12,21,29,15,17,10,7,22,6,20,19,11,2,4,9,25,13,27,14,18,28,8,16,0};      int num[10] = {4,3,8,1,0,5,7,2,9,6};      quick_sort<int>(number,0,29);      quicksort(num,0,9);      for(int i = 0;i < 30;i++)          cout<<number[i]<<" ";          cout<<endl;      for(int i = 0;i < 10;i++)          cout<<num[i]<<" ";          cout<<endl;  }  


0 0