七大排序算法
选择排序
选择排序概述
每次从列表中选取一个最大值(最小值) ,将它和列表最后一个(第一个)元素交换,再将这个这个元素从列表中排除。继续迭代即可。
选择排序实现
#include <iostream>
#define N 10
using namespace std;
void Swap(int *a,int *b);
void selectSort(int *arr);
void printArr(int* arr);
int main(void){
int arr[N]={2,3,1,5,4,6,7,0,9,8};
printArr(arr);
selectSort(arr);
printArr(arr);
return 0;
}
void Swap(int *a,int *b){
int temp=*a;
*a=*b;
*b=temp;
}
// void selectSort(int *arr){
// // int max=arr[0];//假设第一个就是最大的
// int maxIndex=0;
// for(int i=0;i!=N-1;++i){
// for(int j=0;j!=N-1-i;++j){
// if(arr[j]>arr[maxIndex]){
// maxIndex=j;
// }
// }
// if(maxIndex!=N-1-i){//本身不是最后一个元素
// Swap(&arr[maxIndex],&arr[N-1-i]);
// }
// maxIndex=0;
// }
// }
void selectSort(int *arr){
int minIndex=N-1;//假设最后一个是最小的
for(int i=0;i!=N-1;++i){
for(int j=N-1;j>=i;--j){//从前往后排序
if(arr[j]<arr[minIndex]){
minIndex=j;
}
}
if(minIndex!=i){
Swap(&arr[i],&arr[minIndex]);
}
minIndex=N-1;
}
}
void printArr(int *arr){
for(int i=0;i!=N;++i){
printf("%d\t",arr[i]);
}
cout<<endl;
}
冒泡排序
冒泡排序概述
通过重复地遍历未排序的数列,一次比较相邻的两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢得像泡泡一样“浮”到数列的顶端,故而得名!
冒泡排序很好的解决了选择排序对于部分有序数组的重复排序问题。
冒泡排序实现
#include <iostream>
#define N 10
using namespace std;
void bubbleSort(int *arr);
void Swap(int *a,int *b);
void printArr(int *arr);
int main(void){
int arr[N]={2,3,1,5,4,6,7,0,9,8};
printArr(arr);
bubbleSort(arr);
printArr(arr);
return 0;
}
void Swap(int *a,int *b){
int temp=*a;
*a=*b;
*b=temp;
}
void bubbleSort(int *arr){
bool isSwap=false;
for(int i=0;i!=N-1;++i){
isSwap=false;
for(int j=0;j!=N-1-i;++j){
if(arr[j]>arr[j+1]){
Swap(&arr[j],&arr[j+1]);
isSwap=true;
}
}
if(isSwap==false){//没有发生交换,证明数组已经有序
break;
}
}
}
void printArr(int *arr){
for(int i=0;i!=N;++i){
printf("%d\t",arr[i]);
}
cout<<endl;
}
插入排序
插入排序概述
我们假设第一个数据已经有序,从第二个数据开始向前比较,如果前面的有序数据大于当前值,则不断把有序数据后移,直到两个元素相等或者当前数据大于有序数据为止。
插入排序实现
#include <iostream>
using namespace std;
void insertSort(int *arr);
void printArr(int* arr);
int main(void){
int arr[10]={2,3,4,1,9,0,8,7,6,5};
printArr(arr);
insertSort(arr);
printArr(arr);
return 0;
}
void printArr(int * arr){
for(int i=0;i!=10;++i){
cout<<arr[i]<<" ";
}
cout<<endl;
}
void insertSort(int *arr){
int preIndex=0;
int current=0;
for(int i=1;i!=10;++i){
preIndex=i-1;
current=arr[i];
while(preIndex>=0&&arr[preIndex]>current){//一直后移
arr[preIndex+1]=arr[preIndex];
--preIndex;
}
arr[preIndex+1]=current;//一定要记得加一,防止下标越界,因为在覆盖数据后preIndex还--了
}
}
希尔排序—插入的变种
希尔排序概述
希尔排序是插入排序的一种变种,主要是为了应对数据前半部分是有序而后半部分无序的情况。它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序。它与插入排序的不同之处在于,它会优先比较距离较远的元素
希尔排序是把记录按下表的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的元素越来越多,当增量减至 1 时,所有元素被分成一组,实际上等同于执行一次上面讲过的插入排序,算法便终止。
希尔排序实现
#include <iostream>
#define N 10
using namespace std;
void printArr(int *arr);
void shellSort(int *arr);
int main(void){
int arr[N]={2,1,3,5,4,0,9,8,7,6};
printArr(arr);
shellSort(arr);
printArr(arr);
return 0;
}
void printArr(int *arr){
for(int i=0;i!=N;++i){
printf("%d ",arr[i]);
}
printf("\n");
}
void shellSort(int *arr){
for(int gap=N/2;gap>0;gap/=2){//当gap为1时就相当于进行了一次简单插入排序
for(int i=gap;i<N;++i){
int j=i-gap;
int current=arr[i];
while(j>=0&&arr[j]>current){
arr[j+gap]=arr[j];
j-=gap;//不断前移
}
arr[j+gap]=current;
}
}
}
归并排序
归并排序概述
将两个有序数组通过层层比较插入临时数组,然后再拷贝回原数组,如果数组前半部分和后半部分无序。我们采用分治法使它有序,当数组只有一个元素的时候,这个数组就有序了,我们就可以进行归并了。
归并排序实现
#include <iostream>
using namespace std;
void printArr(int*);
void mergerCore(int *arr,int left,int mid,int right,int *temp);//排序的核心内容
void mergerSort(int *arr,int left,int right,int *temp);
int main(void){
int arr[10]={3,2,1,4,5,6,0,9,8,7};
int temp[10]={0};
printArr(arr);
mergerSort(arr,0,9,temp);
printArr(arr);
return 0;
}
void printArr(int*arr){
for(int i=0;i!=10;++i){
printf("%d ",arr[i]);
}
printf("\n");
}
void mergerCore(int *arr,int left,int mid,int right,int *temp){
int i=left;
int j=mid+1;
int k=left;//临时数组下标
while(i<mid&&j<=right){
if(arr[i]<arr[j]){
temp[k++]=arr[i++];
}else{
temp[k++]=arr[j++];
}
}
while(i<mid){
temp[k++]=arr[i++];
}
while(j<=right){
temp[k++]=arr[j++];
}
memcpy(arr+left,temp+left,sizeof(int)*(right-left+1));
}
void mergerSort(int *arr,int left,int right,int* temp){
while(left<right){//当不成立的时候就只有一个元素了
int mid=left+(right-left)/2;
mergerSort(arr,left,mid,temp);
mergerSort(arr,mid+1,right,temp);
mergerCore(arr,left,mid+1,right,temp);
}
}
快速排序
快速排序概述
快速排序和归并排序一样,都是不断的用分治法将原数组分割。不同的是归并排序是用另一个数组来辅助排序,而快排是直接在原数组上进行排序。设第一个数为基准数,从后往前找小于它的数,再从前往后找大于它的数。我们就可以得到一个左边小于基准数,右边大于基准数的标准数组。
快速排序实现
#include <iostream>
using namespace std;
void printArr(int *arr);
int quickCore(int *arr,int low,int high);
void quickSort(int *arr,int low,int high);
int main(void){
int arr[10]={1,2,3,6,40,5,7,9,8,0};
printArr(arr);
quickSort(arr,0,9);
printArr(arr);
return 0;
}
void printArr(int *arr){
for(int i=0;i!=10;++i){
cout<<arr[i]<<" ";
}
cout<<endl;
}
int quickCore(int *arr,int low,int high){
int i=low;
int j=high;
int base=arr[low];
if(low<high){//检查合法性
while(i<j){
while(i<j&&arr[j]>=base){//从右边找一个小于它的数
--j;
}
if(i<j){//已经找到
arr[i++]=arr[j];
}
while(i<j&&arr[i]<base){//在左边找一个大于它的数
++i;
}
if(i<j){
arr[j--]=arr[i];
}
}
arr[i]=base;//用j也一样
}
return i;
}
void quickSort(int *arr,int low,int high){
if(low<high){
int index=quickCore(arr,low,high);//找第一个基准数的坐标
quickSort(arr,low,index-1);
quickSort(arr,index+1,high);
}
}
堆排序
堆排序其实是选择排序的一种变种,在这里就不过多阐述了。