常见排序算法整理
2017-03-30 15:29
176 查看
最近花了点时间把几个常用的排序算法在此做个总结,下面是代码。
1、直接插入排序
输入数组为{16,14,10,8,7,9,3,2,4,1},按照从小到大排序。
右边的无序数不断地往左边的有序数部分进行比较然后插入
16 14 10 8 7 9 3 2 4 1
14 16 10 8 7 9 3 2 4 1
10 14 16 8 7 9 3 2 4 1
8 10 14 16 7 9 3 2 4 1
7 8 10 14 16 9 3 2 4 1
7 8 9 10 14 16 3 2 4 1
3 7 8 9 10 14 16 2 4 1
2 3 7 8 9 10 14 16 4 1
2 3 4 7 8 9 10 14 16 1
1 2 3 4 7 8 9 10 14 16
![](https://img-blog.csdn.net/20170330170154056)
2、冒泡排序
输入数组为{16,14,10,8,7,9,3,2,4,1},按照从小到大排序。
右边无序数中的最小数通过不断交换移到左边
1 16 14 10 8 7 9 3 2 4
1 2 16 14 10 8 7 9 3 4
1 2 3 16 14 10 8 7 9 4
1 2 3 4 16 14 10 8 7 9
1 2 3 4 7 16 14 10 8 9
1 2 3 4 7 8 16 14 10 9
1 2 3 4 7 8 9 16 14 10
1 2 3 4 7 8 9 10 16 14
1 2 3 4 7 8 9 10 14 16
![](https://img-blog.csdn.net/20170330170413909)
3、快速排序
![](https://img-blog.csdn.net/20170405095134506)
![](https://img-blog.csdn.net/20170405095147694)
4、直接选择排序
输入数组为{16,14,10,8,7,9,3,2,4,1},按照从小到大排序。
右边无序数的最小数与无序数中的第一个数进行交换
1 14 10 8 7 9 3 2 4 16
1 2 10 8 7 9 3
14 4 16
1 2 3 8 7 9
10 14 4 16
1 2 3 4 7 9 10 14
8 16
1 2 3 4 7 9 10 14 8 16
1 2 3 4 7 8 10 14
9 16
1 2 3 4 7 8 9 14
10 16
1 2 3 4 7 8 9 10 14 16
1 2 3 4 7 8 9 10 14 16
![](https://img-blog.csdn.net/20170330170611750)
5、堆排序
输入数组为{16,14,10,8,7,9,3,2,4,1},按照从小到大排序。
初始化为最大堆,取出堆顶最大元素跟堆的最后一个元素交换,再重新调整堆
16 14 10 8 7 9 3 2 4 1 初始化为最大堆
14 8 10 4 7 9 3 2 1 16
10 8 9 4 7 1 3 2 14 16
9 8 3 4 7 1 2 10 14 16
8 7 3 4 2 1 9 10 14 16
7 4 3 1 2 8 9 10 14 16
4 2 3 1 7 8 9 10 14 16
3 2 1 4 7 8 9 10 14 16
2 1 3 4 7 8 9 10 14 16
1 2 3 4 7 8 9 10 14 16
![](https://img-blog.csdn.net/20170402143642444)
6、归并排序
归并排序其实要做两件事:
(1)“分解”——将序列每次折半划分。
(2)“合并”——将划分后的序列段两两合并后排序。
![](https://img-blog.csdn.net/20170419184733617)
//合并两个有序的
void Merge(int r[],int r1[],int s,int m,int t)
{
int i=s;
int j=m+1;
int k=s;
//有序排列到r1中
while(i<=m && j<=t){
if(r[i]<=r[j])
r1[k++]=r[i++];
else
r1[k++]=r[j++];
}
if(i<=m)//[i,m]还有剩
{
while(i<=m)
r1[k++]=r[i++];
}
else//[m+1,t]还有剩
{
while(j<=t)
r1[k++]=r[j++];
}
//将r1赋给r
for(int n=s;n<=t;n++)
r
=r1
;
}
//归并排序是空间换时间
void MergeSort(int r[],int r1[],int s,int t)
{
if(s<t)
{
int m=(s+t)/2;//求取中间元素坐标,将数组分为两部分
MergeSort(r,r1,s,m);//[s,m]
MergeSort(r,r1,m+1,t);//[m+1,t]
Merge(r,r1,s,m,t);
}
}
完整可运行代码如下:
参考资料:
[1]【常见排序算法小结】http://blog.csdn.net/whuslei/article/details/6442755
[2]【经典排序算法】http://www.cnblogs.com/kkun/archive/2011/11/23/2260312.html
[3]【八种必须掌握的排序算法】https://zhuanlan.zhihu.com/p/26065419?utm_source=qq&utm_medium=social
1、直接插入排序
输入数组为{16,14,10,8,7,9,3,2,4,1},按照从小到大排序。
右边的无序数不断地往左边的有序数部分进行比较然后插入
16 14 10 8 7 9 3 2 4 1
14 16 10 8 7 9 3 2 4 1
10 14 16 8 7 9 3 2 4 1
8 10 14 16 7 9 3 2 4 1
7 8 10 14 16 9 3 2 4 1
7 8 9 10 14 16 3 2 4 1
3 7 8 9 10 14 16 2 4 1
2 3 7 8 9 10 14 16 4 1
2 3 4 7 8 9 10 14 16 1
1 2 3 4 7 8 9 10 14 16
// 直接插入排序 /* 思想:每次选择一个元素K=data[i]插入到之前已排好序的部分data[0…i-1]中,插入过程中K依次 由后向前与data[0…i-1]中的元素进行比较。若发现发现data[x]>=K,则将K插入到A[x]的后面,插入前需要移动元素。 */ void InsertSort(vector<int> & data) { int n = data.size();//数组长度 int i,j; int temp; for(i=0;i<n;i++) { temp = data[i]; j = i-1;//从右向左在有序区data[0...i-1]找data[i]的插入位置 while(j>=0 && temp<data[j]) { data[j+1] = data[j];//将值大于data[i]向右移动 j--; } data[j+1] = temp;//在j+1处插入data[i] } }
2、冒泡排序
输入数组为{16,14,10,8,7,9,3,2,4,1},按照从小到大排序。
右边无序数中的最小数通过不断交换移到左边
1 16 14 10 8 7 9 3 2 4
1 2 16 14 10 8 7 9 3 4
1 2 3 16 14 10 8 7 9 4
1 2 3 4 16 14 10 8 7 9
1 2 3 4 7 16 14 10 8 9
1 2 3 4 7 8 16 14 10 9
1 2 3 4 7 8 9 16 14 10
1 2 3 4 7 8 9 10 16 14
1 2 3 4 7 8 9 10 14 16
//冒泡排序 //从最右侧的元素开始搜索并交换,找出最小的数移到无序的最左位置 void BubbleSort(vector<int> & data) { int n = data.size();//数组长度 int i,j; int temp; for(i=0;i<n-1;i++)//n趟 { for(j=n-1;j>i;j--)//找出本趟次最小的数,移到无序的最左处 { if(data[j]<data[j-1])//后面的数比前面的小就交换 { temp = data[j]; data[j] = data[j-1]; data[j-1] = temp; } } } }
3、快速排序
//快速排序 //最核心的思想是将小的部分放在左边,大的部分放到右边,实现分割。 //每次都需要和中轴元素交换,因此原来的顺序就可能被打乱,所以不稳定 void QuickSort(int data[],int s,int t) { int i=s,j=t; int temp; if(s<t) { temp = data[s];//取data[s...t]最左侧的元素作为中轴元素 while(i!=j){ while(j>i && data[j]>temp) j--;//从右往左找到第一个比temp值要小的数data[j] if(i<j){data[i]=data[j];i++;}//data[j]移到左侧,i++ while(i<j && data[i]<temp) i++;//从左往右找到第一个比temp值要大的数 if(i<j){data[j]=data[i];j--;}//data[i]移到右侧,j-- } data[i] = temp; QuickSort(data,s,i-1);//对左段继续分割 QuickSort(data,i+1,t);//对右段继续分割 } }
4、直接选择排序
输入数组为{16,14,10,8,7,9,3,2,4,1},按照从小到大排序。
右边无序数的最小数与无序数中的第一个数进行交换
1 14 10 8 7 9 3 2 4 16
1 2 10 8 7 9 3
14 4 16
1 2 3 8 7 9
10 14 4 16
1 2 3 4 7 9 10 14
8 16
1 2 3 4 7 9 10 14 8 16
1 2 3 4 7 8 10 14
9 16
1 2 3 4 7 8 9 14
10 16
1 2 3 4 7 8 9 10 14 16
1 2 3 4 7 8 9 10 14 16
// 直接选择排序 void SelectSort(vector<int> & data) { int n = data.size();//数组长度 int i,j,k; int temp; for(i=0;i<n-1;i++) { k = i; for(j=i+1;j<n;j++)//在右边无序数中找最小数 { if(data[j]<data[k])//记录最小数的位置 k=j; } if(k!=i)//最小数data[k]跟无序数中首个数data[i]交换 { temp = data[i]; data[i] = data[k]; data[k] = temp; } } }
5、堆排序
输入数组为{16,14,10,8,7,9,3,2,4,1},按照从小到大排序。
初始化为最大堆,取出堆顶最大元素跟堆的最后一个元素交换,再重新调整堆
16 14 10 8 7 9 3 2 4 1 初始化为最大堆
14 8 10 4 7 9 3 2 1 16
10 8 9 4 7 1 3 2 14 16
9 8 3 4 7 1 2 10 14 16
8 7 3 4 2 1 9 10 14 16
7 4 3 1 2 8 9 10 14 16
4 2 3 1 7 8 9 10 14 16
3 2 1 4 7 8 9 10 14 16
2 1 3 4 7 8 9 10 14 16
1 2 3 4 7 8 9 10 14 16
//调整堆,交换较大数 void adjustHeap(int A[],int s,int e) { int i = s,j=2*i,tmp;//数组第j个元素是第i个的左子树 tmp = A[i-1]; while(j<=e) { if(j<e && A[j-1]<A[j])//取左、右子树中的较大者 j++; if(A[j-1]>tmp) { A[i-1]=A[j-1];//交换较大数 i=j; j=2*i;//更新位置,进行下一轮调整 } else { break; } } A[i-1] = tmp;//最终位置 } //堆排序 void heapsort(int data[],int n) { int i,tmp; //初始化为最大堆 for(i=n/2;i>=1;i--) { adjustHeap(data,i,n); } for(i=n;i>=2;i--)//i==1只有一个元素就不用调整了 { tmp = data[0];//取出堆顶最大元素跟堆的最后一个元素交换 data[0] = data[i-1]; data[i-1] = tmp; adjustHeap(data,1,i-1);//此时堆大小-1 } }
6、归并排序
归并排序其实要做两件事:
(1)“分解”——将序列每次折半划分。
(2)“合并”——将划分后的序列段两两合并后排序。
//合并两个有序的
void Merge(int r[],int r1[],int s,int m,int t)
{
int i=s;
int j=m+1;
int k=s;
//有序排列到r1中
while(i<=m && j<=t){
if(r[i]<=r[j])
r1[k++]=r[i++];
else
r1[k++]=r[j++];
}
if(i<=m)//[i,m]还有剩
{
while(i<=m)
r1[k++]=r[i++];
}
else//[m+1,t]还有剩
{
while(j<=t)
r1[k++]=r[j++];
}
//将r1赋给r
for(int n=s;n<=t;n++)
r
=r1
;
}
//归并排序是空间换时间
void MergeSort(int r[],int r1[],int s,int t)
{
if(s<t)
{
int m=(s+t)/2;//求取中间元素坐标,将数组分为两部分
MergeSort(r,r1,s,m);//[s,m]
MergeSort(r,r1,m+1,t);//[m+1,t]
Merge(r,r1,s,m,t);
}
}
完整可运行代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <algorithm>
#include <math.h>
using namespace std;
// 直接插入排序 /* 思想:每次选择一个元素K=data[i]插入到之前已排好序的部分data[0…i-1]中,插入过程中K依次 由后向前与data[0…i-1]中的元素进行比较。若发现发现data[x]>=K,则将K插入到A[x]的后面,插入前需要移动元素。 */ void InsertSort(vector<int> & data) { int n = data.size();//数组长度 int i,j; int temp; for(i=0;i<n;i++) { temp = data[i]; j = i-1;//从右向左在有序区data[0...i-1]找data[i]的插入位置 while(j>=0 && temp<data[j]) { data[j+1] = data[j];//将值大于data[i]向右移动 j--; } data[j+1] = temp;//在j+1处插入data[i] } }
//冒泡排序
//从最右侧的元素开始搜索并交换,找出最小的数移到无序的最左位置
void BubbleSort(vector<int> & data) {
int n = data.size();//数组长度
int i,j;
int temp;
for(i=0;i<n-1;i++)//n趟
{
for(j=n-1;j>i;j--)//找出本趟次最小的数,移到无序的最左处
{
if(data[j]<data[j-1])//后面的数比前面的小就交换
{
temp = data[j];
data[j] = data[j-1];
data[j-1] = temp;
}
}
}
}
//快速排序 //最核心的思想是将小的部分放在左边,大的部分放到右边,实现分割。 //每次都需要和中轴元素交换,因此原来的顺序就可能被打乱,所以不稳定 void QuickSort(int data[],int s,int t) { int i=s,j=t; int temp; if(s<t) { temp = data[s];//取data[s...t]最左侧的元素作为中轴元素 while(i!=j){ while(j>i && data[j]>temp) j--;//从右往左找到第一个比temp值要小的数data[j] if(i<j){data[i]=data[j];i++;}//data[j]移到左侧,i++ while(i<j && data[i]<temp) i++;//从左往右找到第一个比temp值要大的数 if(i<j){data[j]=data[i];j--;}//data[i]移到右侧,j-- } data[i] = temp; QuickSort(data,s,i-1);//对左段继续分割 QuickSort(data,i+1,t);//对右段继续分割 } }
// 直接选择排序 void SelectSort(vector<int> & data) { int n = data.size();//数组长度 int i,j,k; int temp; for(i=0;i<n-1;i++) { k = i; for(j=i+1;j<n;j++)//在右边无序数中找最小数 { if(data[j]<data[k])//记录最小数的位置 k=j; } if(k!=i)//最小数data[k]跟无序数中首个数data[i]交换 { temp = data[i]; data[i] = data[k]; data[k] = temp; } } }
//调整堆,交换较大数
void adjustHeap(int A[],int s,int e)
{
int i = s,j=2*i,tmp;//[j]是[i]的左子树
tmp = A[i-1];
while(j<=e)
{
if(j<e && A[j-1]<A[j])//取左、右子树中的较大者
j++;
if(A[j-1]>tmp)
{
A[i-1]=A[j-1];//交换较大数
i=j;
j=2*i;//更新位置,进行下一轮调整
}
else
{
break;
}
}
A[i-1] = tmp;//最终位置
}
//堆排序
void heapsort(int data[],int n)
{
int i,tmp;
//初始化为最大堆
for(i=n/2;i>=1;i--)
{
adjustHeap(data,i,n);
}
for(i=n;i>=2;i--)//i==1只有一个元素就不用调整了
{
tmp = data[0];//取出堆顶最大元素跟堆的最后一个元素交换
data[0] = data[i-1];
data[i-1] = tmp;
adjustHeap(data,1,i-1);//此时堆大小-1
}
}
//合并两个有序的
void Merge(int r[],int r1[],int s,int m,int t)
{
int i=s;
int j=m+1;
int k=s;
//有序排列到r1中
while(i<=m && j<=t){
if(r[i]<=r[j])
r1[k++]=r[i++];
else
r1[k++]=r[j++];
}
if(i<=m)//[i,m]还有剩
{
while(i<=m)
r1[k++]=r[i++];
}
else//[m+1,t]还有剩
{
while(j<=t)
r1[k++]=r[j++];
}
//将r1赋给r
for(int n=s;n<=t;n++)
r
=r1
;
}
//归并排序是空间换时间
void MergeSort(int r[],int r1[],int s,int t)
{
if(s<t)
{
int m=(s+t)/2;//求取中间元素坐标,将数组分为两部分
MergeSort(r,r1,s,m);//[s,m]
MergeSort(r,r1,m+1,t);//[m+1,t]
Merge(r,r1,s,m,t);
}
}
int main()
{
//数组初始化vector
int iarray[]={16,14,10,8,7,9,3,2,4,1};
//count: iarray数组个数
size_t count=sizeof(iarray)/sizeof(int);
//int数组初始化 ivec3
vector<int> a(iarray,iarray+count);
#if 0
BubbleSort(a);
for(int i=0;i<count;i++)
{
printf("%d\n",a[i]);
}
#endif
#if 1
//QuickSort(iarray,0,count-1);
heapsort(iarray,count);
for(int i=0;i<count;i++)
{
printf("%d\n",iarray[i]);
}
#endif
system("pause");
return 0;
}
参考资料:
[1]【常见排序算法小结】http://blog.csdn.net/whuslei/article/details/6442755
[2]【经典排序算法】http://www.cnblogs.com/kkun/archive/2011/11/23/2260312.html
[3]【八种必须掌握的排序算法】https://zhuanlan.zhihu.com/p/26065419?utm_source=qq&utm_medium=social
相关文章推荐
- 常见排序算法整理(二)----希尔排序,选择排序
- 常见排序算法整理
- IT求职整理Ⅲ---常见排序算法小结
- 常见排序算法整理
- 数据结构常见的八大排序算法(详细整理)
- 常见排序算法整理
- 常见排序算法整理
- 常见排序算法:插入排序 <整理>
- Java_常见排序算法整理
- 常见排序算法代码整理
- 几种常见的排序算法整理
- 常见排序算法整理(一)----冒泡排序、直接插入排序
- 常见排序算法整理(三)----归并排序、快速排序
- 自己整理的几种常见排序算法,及时间复杂度空间复杂度。c++编程
- 整理的常见排序算法
- 常见排序算法整理-
- Java常见的垃圾收集器GC算法整理
- 几种常见模式识别算法整理和总结【转】
- zz 关于常见排序算法的稳定性分析和结论
- VS中常见的错误整理