《算法导论》(一)--插入排序与合并排序

插入排序

书上说的很好,用打牌作比方。就是一边是排好序的,剩下的是待排序的,每次取一个待排序的元素,找到按序的位置,插入已排好序的部分中。元素取完也就结束了。复杂度O(n^2)。

代码:

#include <iostream> using namespace std; #define LENGTH 11 void insert_sort(int array[],int len) { int i,j; for (i=1;i<len;i++) { int key=array[i]; for (j=i-1;j>=0&&array[j]>key;j--) { array[j+1]=array[j]; } array[j+1]=key; } } int main() { int array[LENGTH]={9,3,5,12,7,34,56,28,16,4,10}; int i=0; for (i=0;i<LENGTH;i++) { cout<<array[i]<<" "; } cout<<endl; insert_sort(array,LENGTH);//sort for (i=0;i<LENGTH;i++) { cout<<array[i]<<" "; } cout<<endl; }

 

合并排序

合并排序是一种分治法,实现上用了递归结构。过程是:先将待排序的元素分为两部分,一般是对等长度的两部分,称为左右L、R,先分别将L,R进行合并排序,然后将排序好的L、R合并在一起,则所有元素都有序。复杂度O(nlgn)。

代码

#include <iostream> using namespace std; #define LENGTH 10 void merge(int array[],int start,int middle,int end) { int i,j,k; int n1=middle-start+1,n2=end-middle; int *L=new int[n1+1],*R=new int[n2+1]; for (i=0;i<n1;i++) { L[i]=array[start+i]; } for (i=0;i<n2;i++) { R[i]=array[middle+i+1]; } L[n1]=INT_MAX; R[n2]=INT_MAX; i=0,j=0; for (k=start;k<=end;k++) { if(L[i]<=R[j]) { array[k]=L[i]; i++; } else { array[k]=R[j]; j++; } } } void merge_sort(int array[],int start,int end) { int i,j; if(start<end) { int middle=(start+end)/2; merge_sort(array,start,middle); merge_sort(array,middle+1,end); merge(array,start,middle,end); } } int main() { int i=0; int array[LENGTH]={9,12,5,24,8,7,15,10,0,22}; for (i=0;i<LENGTH;i++) { cout<<array[i]<<" "; } cout<<endl; merge_sort(array,0,LENGTH-1); for (i=0;i<LENGTH;i++) { cout<<array[i]<<" "; } cout<<endl; return 0; }  

 

合并排序的扩展应用

对合并排序稍作一些改动,可以以O(nlgn)的复杂度实现其他功能。

思考题2.3.7

思路:

I  对集合S中的元素进行排序,选择复杂度为O(nlgn)的排序算法,这里是合并排序
II 从两头开始遍历排序后S的元素,下标分别为i、j,若S[i]+S[j]==x,返回;若S[i]+S[j]>x,j--;若S[i]+S[j]<x,i++

代码

#include <iostream> using namespace std; #define LENGTH 10 void merge(int array[],int start,int middle,int end) { int i,j,k; int n1=middle-start+1,n2=end-middle; int *L=new int[n1+1],*R=new int[n2+1]; for (i=0;i<n1;i++) { L[i]=array[start+i]; } for (i=0;i<n2;i++) { R[i]=array[middle+i+1]; } L[n1]=INT_MAX; R[n2]=INT_MAX; i=0,j=0; for (k=start;k<=end;k++) { if(L[i]<=R[j]) { array[k]=L[i]; i++; } else { array[k]=R[j]; j++; } } } void merge_sort(int array[],int start,int end) { int i,j; if(start<end) { int middle=(start+end)/2; merge_sort(array,start,middle); merge_sort(array,middle+1,end); merge(array,start,middle,end); } } bool find_two_ele(int array[],int len,int x,int &x1,int &x2) { int i,j; for (i=0,j=len-1;i<len;) { int sum=array[i]+array[j]; if(sum==x) { x1=array[i]; x2=array[j]; return true; } else if(sum>x) { j--; } else { i++; } } return false; } int main() { int i=0; int array[LENGTH]={9,12,5,24,8,7,15,10,0,22}; merge_sort(array,0,LENGTH-1); int x=15,x1,x2; if(find_two_ele(array,LENGTH,x,x1,x2)) { cout<<"Yes."<<x<<"="<<x1<<"+"<<x2<<endl; }else { cout<<"No."<<endl; } return 0; }

练习题2-4

逆序对问题,可以在合并的时候统计有多少逆序对。

代码

 /**************** 逆序对问题 ****************/ #include <iostream> using namespace std; #define LENGTH 10 int Num=0; int merge(int array[],int start,int middle,int end) { int i,j,k,count=0; int n1=middle-start+1,n2=end-middle; int *L=new int[n1+1],*R=new int[n2+1]; for (i=0;i<n1;i++) { L[i]=array[start+i]; } for (i=0;i<n2;i++) { R[i]=array[middle+i+1]; } L[n1]=INT_MAX,R[n2]=INT_MAX; i=0,j=0; for (k=start;k<=end;k++) { if(L[i]<R[j]) { array[k]=L[i]; i++; } else { array[k]=R[j]; count+=middle-start-i+1;//count j++; } } return count; } int merge_sort(int array[],int start,int end) { if(start<end) { int middle=(start+end)/2; merge_sort(array,start,middle); merge_sort(array,middle+1,end); Num+=merge(array,start,middle,end); return Num; } } int main() { int array[LENGTH]={9,12,5,24,8,7,15,10,0,22}; cout<<merge_sort(array,0,LENGTH-1)<<endl; for (int i=0;i<LENGTH;i++) { cout<<array[i]<<" "; } cout<<endl; return 0; }

你可能感兴趣的:(算法,insert,扩展,merge,n2)