复习一下各种排序算法 1.冒泡 2.选择 3.插入 4.快速排序 5.堆排序 6.归并排序 7.希尔排序 8.基数排序
有个博客讲原理讲的挺好的:
https://www.cnblogs.com/chengxiao/p/6104371.html
冒泡排序
每次交换相邻两个元素
------冒泡排序------
5 8 3 4 9 6 1 2 7 0
5 3 4 8 6 1 2 7 0 9
3 4 5 6 1 2 7 0 8 9
3 4 5 1 2 6 0 7 8 9
3 4 1 2 5 0 6 7 8 9
3 1 2 4 0 5 6 7 8 9
1 2 3 0 4 5 6 7 8 9
1 2 0 3 4 5 6 7 8 9
1 0 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
void Sort1(int data[],int size){ cout<<"------冒泡排序------"<<endl; for(int i=0;i<size-1;i++){ Show(data); for(int j=0;j<size-i-1;j++){ if(data[j]>data[j+1]){ int temp = data[j]; data[j] = data[j+1]; data[j+1] = temp; } } } }
选择排序
遍历找到未排序区最小,然后放到已排序区后面
------选择排序------
5 8 3 4 9 6 1 2 7 0
0 8 3 4 9 6 1 2 7 5
0 1 3 4 9 6 8 2 7 5
0 1 2 4 9 6 8 3 7 5
0 1 2 3 9 6 8 4 7 5
0 1 2 3 4 6 8 9 7 5
0 1 2 3 4 5 8 9 7 6
0 1 2 3 4 5 6 9 7 8
0 1 2 3 4 5 6 7 9 8
0 1 2 3 4 5 6 7 8 9
void Sort2(int data[],int size){ cout<<"------选择排序------"<<endl; for(int i=0;i<size-1;i++){ Show(data); //遍历未排序,找出最小的数 int min=i;//min是最小的数的索引 for(int j=i+1;j<size;j++){ if(data[min]>data[j]){ min=j; } } //最小数与已排区域后面第一个元素交换位置 Swap(data[min],data[i]); } }
插入排序
每次将一个元素插入已排序区域相应位置
------插入排序------
5 8 3 4 9 6 1 2 7 0
5 8 3 4 9 6 1 2 7 0
3 5 8 4 9 6 1 2 7 0
3 4 5 8 9 6 1 2 7 0
3 4 5 8 9 6 1 2 7 0
3 4 5 6 8 9 1 2 7 0
1 3 4 5 6 8 9 2 7 0
1 2 3 4 5 6 8 9 7 0
1 2 3 4 5 6 7 8 9 0
0 1 2 3 4 5 6 7 8 9
void Sort3(int data[],int size){ cout<<"------插入排序------"<<endl; for(int i=1;i<size;i++){ Show(data); int temp=data[i]; int j=i-1; //把已排区域后第一个数插入到已排区域 //这里做了优化,交换次数少了 while(j>=0&&data[j]>temp){ data[j+1]=data[j]; j--; } data[j+1]=temp; } }
快速排序
选择一个枢轴点,把小于它的放左边,大于他的放右边
然后对左右两边继续应用快速排序
------快速排序------
5 8 3 4 9 6 1 2 7 0
0 2 3 4 1 5 6 9 7 8
0 2 3 4 1 5 6 9 7 8
0 1 2 4 3 5 6 9 7 8
0 1 2 3 4 5 6 9 7 8
0 1 2 3 4 5 6 9 7 8
0 1 2 3 4 5 6 8 7 9
0 1 2 3 4 5 6 7 8 9
void Sort4fun(int data[],int left,int right){ //当左已经大于或等于右,最多只有一个元素,不用排序了 if(left>=right)return; Show(data); //选择区域中第一个数作为枢轴 int choice = data[left]; int i=left,j=right; while(i<j){ //从右向左找比枢轴小的,保存到前面 while(i<j&&choice<data[j])j--; if(i<j){data[i]=data[j];i++;} //从左往右找比枢轴大的,保存到后面 while(i<j&&choice>data[i])i++; if(i<j){data[j]=data[i];j--;} } //最终,左右标志重合,这个位置就是枢轴存的位置 data[i]=choice; //对枢轴两侧的元素分别调用快速排序 Sort4fun(data,i+1,right); Sort4fun(data,left,i-1); } void Sort4(int data[],int size){ cout<<"------快速排序------"<<endl; Sort4fun(data,0,size-1); }
堆排序
将数组视为完全二叉树,把他调整为一个堆,
依次对换第一个元素和最后一个元素,并调整堆。
------堆排序--------
5 8 3 4 9 6 1 2 7 0
9 8 6 7 5 3 1 2 4 0
8 7 6 4 5 3 1 2 0 9
7 5 6 4 0 3 1 2 8 9
6 5 3 4 0 2 1 7 8 9
5 4 3 1 0 2 6 7 8 9
4 2 3 1 0 5 6 7 8 9
3 2 0 1 4 5 6 7 8 9
2 1 0 3 4 5 6 7 8 9
1 0 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
void Sort5fun(int data[],int target,int size){ //调整堆 int left = target*2+1; int right = target*2+2; //如果左节点都不存在,那么它没有子节点可以直接退出 if(left>=size)return; //选择左右节点中最大的 int max = left; //如果没有右节点,只判断是否需要与左交换即可 if(right<size&&data[max]<data[right]){ max=right; } //如果左右节点中最大的大于自己,交换并继续调整这个子节点 //否则堆已经成立,调整结束 if(data[max]>data[target]){ Swap(data[max],data[target]); ////查看每次排序交换的元素 // printf("Swap {[%d]=%d} , {[%d]=%d} " // ,max,data[max],target,data[target]); Sort5fun(data,max,size); } } //堆其实就是一个以数组方式存储的完全二叉树 //对于节点i,左子节点为2*i+1,右子节点为2*i+2 void Sort5(int data[],int size){ cout<<"------堆排序--------"<<endl; Show(data); //建堆 for(int i=size-1;i>=0;i--){ Sort5fun(data,i,size); } //调整 for(int i=size-1;i>0;i--){ Show(data); Swap(data[i],data[0]); Sort5fun(data,0,i); } }
归并排序
把数组逐渐分解为小区间,对每两个个小区间使用
合并有序数组算法,最终合并为一个
------归并排序------
5 8 3 4 9 6 1 2 7 0
5 8 3 4 9 6 1 2 7 0
5 8 3 4 9 6 1 2 7 0
5 8 3 4 9 6 1 2 7 0
3 5 8 4 9 6 1 2 7 0
3 4 5 8 9 6 1 2 7 0
3 4 5 8 9 6 1 2 7 0
3 4 5 8 9 6 1 2 7 0
3 4 5 8 9 1 2 6 7 0
0 1 2 3 4 5 6 7 8 9
void Sort6fun(int data[],int left,int right,int temp[]){ if(left>=right)return; Show(data); //将数据分为两个组 int mid=(left+right)/2; Sort6fun(data,left,mid,temp); Sort6fun(data,mid+1,right,temp); //执行两路归并 int i=left,j=mid+1,k=left; while(i<=mid&&j<=right){ if(data[i]<data[j]){ temp[k]=data[i]; k++;i++; }else{ temp[k]=data[j]; k++;j++; } } //最后可能有一些数据没有加入 while(i<=mid){ temp[k]=data[i];k++;i++; } while(j<=right){ temp[k]=data[j];k++;j++; } //两路归并完成,数据复制到原数组中 k=left; while(k<=right){ data[k]=temp[k]; k++; } } void Sort6(int data[],int size){ cout<<"------归并排序------"<<endl; int temp[size]; Sort6fun(data,0,size-1,temp); }
希尔排序
间隔若干元素的视为一组,应用插入排序,
然后减少间隔,直到间隔达到1
gap为size/2,以后每次都除2
------希尔排序------
5 8 3 4 9 6 1 2 7 0
5 1 2 4 0 6 8 3 7 9
0 1 2 3 5 4 7 6 8 9
0 1 2 3 4 5 6 7 8 9
void Sort7(int data[],int size){ cout<<"------希尔排序------"<<endl; for(int gap=size/2;gap>0;gap/=2){ Show(data); for(int n=0;n<gap;n++){ //内部为一个简单插入排序 for(int i=n+gap;i<size;i+=gap){ int j=i-gap,temp=data[i]; while(0<=j&&temp<data[j]){ data[j+gap]=data[j]; j-=gap; } data[j+gap]=temp; } } } }
/* 实现各种排序算法 1.冒泡 2.选择 3.插入 4.快速排序 5.堆排序 6.归并排序 7.希尔排序 8.基数排序 (基本是链表实现了,这里没实现) */ #include<iostream> #include<stdio.h> using namespace std; //在这里改变待待排序数据 int source[]={5,8,3,4,9,6,1,2,7,0}; //每次改变数据,需要修改数据个数!!! int count=10; //输出数组中全部数据 void Show(int data[]){ for(int i=0;i<count;i++){ cout<<data[i]<<" "; }cout<<endl; } void Copy(int data[],int target[],int size){ for(int i=0;i<size;i++){ target[i]=data[i]; } } void Swap(int &a,int &b){ int temp = a; a=b;b=temp; } //冒泡排序 //每次交换相邻两个元素 /* ------冒泡排序------ 5 8 3 4 9 6 1 2 7 0 5 3 4 8 6 1 2 7 0 9 3 4 5 6 1 2 7 0 8 9 3 4 5 1 2 6 0 7 8 9 3 4 1 2 5 0 6 7 8 9 3 1 2 4 0 5 6 7 8 9 1 2 3 0 4 5 6 7 8 9 1 2 0 3 4 5 6 7 8 9 1 0 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 */ void Sort1(int data[],int size){ cout<<"------冒泡排序------"<<endl; for(int i=0;i<size-1;i++){ Show(data); for(int j=0;j<size-i-1;j++){ if(data[j]>data[j+1]){ int temp = data[j]; data[j] = data[j+1]; data[j+1] = temp; } } } } //选择排序 //遍历找到未排序区最小,然后放到已排序区后面 /* ------选择排序------ 5 8 3 4 9 6 1 2 7 0 0 8 3 4 9 6 1 2 7 5 0 1 3 4 9 6 8 2 7 5 0 1 2 4 9 6 8 3 7 5 0 1 2 3 9 6 8 4 7 5 0 1 2 3 4 6 8 9 7 5 0 1 2 3 4 5 8 9 7 6 0 1 2 3 4 5 6 9 7 8 0 1 2 3 4 5 6 7 9 8 0 1 2 3 4 5 6 7 8 9 */ void Sort2(int data[],int size){ cout<<"------选择排序------"<<endl; for(int i=0;i<size-1;i++){ Show(data); //遍历未排序,找出最小的数 int min=i;//min是最小的数的索引 for(int j=i+1;j<size;j++){ if(data[min]>data[j]){ min=j; } } //最小数与已排区域后面第一个元素交换位置 Swap(data[min],data[i]); } } //插入排序 //每次将一个元素插入已排序区域相应位置 /* ------插入排序------ 5 8 3 4 9 6 1 2 7 0 5 8 3 4 9 6 1 2 7 0 3 5 8 4 9 6 1 2 7 0 3 4 5 8 9 6 1 2 7 0 3 4 5 8 9 6 1 2 7 0 3 4 5 6 8 9 1 2 7 0 1 3 4 5 6 8 9 2 7 0 1 2 3 4 5 6 8 9 7 0 1 2 3 4 5 6 7 8 9 0 0 1 2 3 4 5 6 7 8 9 */ void Sort3(int data[],int size){ cout<<"------插入排序------"<<endl; for(int i=1;i<size;i++){ Show(data); int temp=data[i]; int j=i-1; //把已排区域后第一个数插入到已排区域 //这里做了优化,交换次数少了 while(j>=0&&data[j]>temp){ data[j+1]=data[j]; j--; } data[j+1]=temp; } } //快速排序 //选择一个枢轴点,把小于它的放左边,大于他的放右边 //然后对左右两边继续应用快速排序 /* ------快速排序------ 5 8 3 4 9 6 1 2 7 0 0 2 3 4 1 5 6 9 7 8 0 2 3 4 1 5 6 9 7 8 0 1 2 4 3 5 6 9 7 8 0 1 2 3 4 5 6 9 7 8 0 1 2 3 4 5 6 9 7 8 0 1 2 3 4 5 6 8 7 9 0 1 2 3 4 5 6 7 8 9 */ void Sort4fun(int data[],int left,int right){ //当左已经大于或等于右,最多只有一个元素,不用排序了 if(left>=right)return; Show(data); //选择区域中第一个数作为枢轴 int choice = data[left]; int i=left,j=right; while(i<j){ //从右向左找比枢轴小的,保存到前面 while(i<j&&choice<data[j])j--; if(i<j){data[i]=data[j];i++;} //从左往右找比枢轴大的,保存到后面 while(i<j&&choice>data[i])i++; if(i<j){data[j]=data[i];j--;} } //最终,左右标志重合,这个位置就是枢轴存的位置 data[i]=choice; //对枢轴两侧的元素分别调用快速排序 Sort4fun(data,i+1,right); Sort4fun(data,left,i-1); } void Sort4(int data[],int size){ cout<<"------快速排序------"<<endl; Sort4fun(data,0,size-1); } //堆排序 //将数组视为完全二叉树,把他调整为一个堆, //依次对换第一个元素和最后一个元素,并调整堆。 /* ------堆排序-------- 5 8 3 4 9 6 1 2 7 0 9 8 6 7 5 3 1 2 4 0 8 7 6 4 5 3 1 2 0 9 7 5 6 4 0 3 1 2 8 9 6 5 3 4 0 2 1 7 8 9 5 4 3 1 0 2 6 7 8 9 4 2 3 1 0 5 6 7 8 9 3 2 0 1 4 5 6 7 8 9 2 1 0 3 4 5 6 7 8 9 1 0 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 */ void Sort5fun(int data[],int target,int size){ //调整堆 int left = target*2+1; int right = target*2+2; //如果左节点都不存在,那么它没有子节点可以直接退出 if(left>=size)return; //选择左右节点中最大的 int max = left; //如果没有右节点,只判断是否需要与左交换即可 if(right<size&&data[max]<data[right]){ max=right; } //如果左右节点中最大的大于自己,交换并继续调整这个子节点 //否则堆已经成立,调整结束 if(data[max]>data[target]){ Swap(data[max],data[target]); ////查看每次排序交换的元素 // printf("Swap {[%d]=%d} , {[%d]=%d} " // ,max,data[max],target,data[target]); Sort5fun(data,max,size); } } //堆其实就是一个以数组方式存储的完全二叉树 //对于节点i,左子节点为2*i+1,右子节点为2*i+2 void Sort5(int data[],int size){ cout<<"------堆排序--------"<<endl; Show(data); //建堆 for(int i=size-1;i>=0;i--){ Sort5fun(data,i,size); } //调整 for(int i=size-1;i>0;i--){ Show(data); Swap(data[i],data[0]); Sort5fun(data,0,i); } } //归并排序 //把数组逐渐分解为小区间,对每两个个小区间使用 //合并有序数组算法,最终合并为一个 /* ------归并排序------ 5 8 3 4 9 6 1 2 7 0 5 8 3 4 9 6 1 2 7 0 5 8 3 4 9 6 1 2 7 0 5 8 3 4 9 6 1 2 7 0 3 5 8 4 9 6 1 2 7 0 3 4 5 8 9 6 1 2 7 0 3 4 5 8 9 6 1 2 7 0 3 4 5 8 9 6 1 2 7 0 3 4 5 8 9 1 2 6 7 0 0 1 2 3 4 5 6 7 8 9 */ void Sort6fun(int data[],int left,int right,int temp[]){ if(left>=right)return; Show(data); //将数据分为两个组 int mid=(left+right)/2; Sort6fun(data,left,mid,temp); Sort6fun(data,mid+1,right,temp); //执行两路归并 int i=left,j=mid+1,k=left; while(i<=mid&&j<=right){ if(data[i]<data[j]){ temp[k]=data[i]; k++;i++; }else{ temp[k]=data[j]; k++;j++; } } //最后可能有一些数据没有加入 while(i<=mid){ temp[k]=data[i];k++;i++; } while(j<=right){ temp[k]=data[j];k++;j++; } //两路归并完成,数据复制到原数组中 k=left; while(k<=right){ data[k]=temp[k]; k++; } } void Sort6(int data[],int size){ cout<<"------归并排序------"<<endl; int temp[size]; Sort6fun(data,0,size-1,temp); } //希尔排序 //间隔若干元素的视为一组,应用插入排序, //然后减少间隔,直到间隔达到1 //gap为size/2,以后每次都除2 /* ------希尔排序------ 5 8 3 4 9 6 1 2 7 0 5 1 2 4 0 6 8 3 7 9 0 1 2 3 5 4 7 6 8 9 0 1 2 3 4 5 6 7 8 9 */ void Sort7(int data[],int size){ cout<<"------希尔排序------"<<endl; for(int gap=size/2;gap>0;gap/=2){ Show(data); for(int n=0;n<gap;n++){ //内部为一个简单插入排序 for(int i=n+gap;i<size;i+=gap){ int j=i-gap,temp=data[i]; while(0<=j&&temp<data[j]){ data[j+gap]=data[j]; j-=gap; } data[j+gap]=temp; } } } } int main(){ int data[count]; Copy(source,data,count); Sort1(data,count); Show(data); Copy(source,data,count); Sort2(data,count); Show(data); Copy(source,data,count); Sort3(data,count); Show(data); Copy(source,data,count); Sort4(data,count); Show(data); Copy(source,data,count); Sort5(data,count); Show(data); Copy(source,data,count); Sort6(data,count); Show(data); Copy(source,data,count); Sort7(data,count); Show(data); return 0; }