您的位置:首页 > 其它

常见排序算法整理

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



// 直接插入排序
/*
思想:每次选择一个元素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

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: