快速排序&&归并排序

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

今天做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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值