前几天刚学了但是没做题实践一下,总体感觉就是分治,归并。有点搞不懂有什么太大区别。
今天做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;
}