您的位置:首页 > 编程语言

菜鸟学习从入门到放弃(二)排序算法总结与应用(附代码)

2016-10-20 16:27 996 查看
排序算法的总结,水平有限,欢迎指正。文章介绍插入排序(直接插入排序—>希尔排序)、交换排序(冒泡排序—>快速排序)、选择排序(简单选择排序—>堆排序)、归并排序、桶排序、基数排序和计数排序共10种排序算法。最后有10种排序算法性能的比较的表格。

大部分都是别人的东西,主要参考:王红梅等.数据结构(C++版).清华大学出版社;算法导论(第三版)。我只是搬运工,出处不一定注得明。代码实现直接插入排序、冒泡排序、简单选择排序、希尔排序和快速排序。

常用排序算法主要是插入排序、交换排序和选择排序,所以先介绍。

(一)插入排序(直接插入排序—>希尔排序)

1、直接插入排序

基本思想:一次将待排序中的每一个记录插入到一个已排好序的序列,直到全部记录都排好序。类似于玩纸牌你已经将35789排好摸到一张6,就从3开始比较,3比6小,5比6小,到7比6大,所以6插到5和7之间。具体步骤如图:



第一步:将待排序序列分为有序区和无序区,初始状态有序区为序列第一个数,无序区为序列剩下数字。

第二步:将无序区第一个数字与有序区比较,并将其插入到适合的位置。

第三步:重复第二步直到无序区数字全部进入有序区。

2、希尔排序

希尔排序是对直接插入法的一种改进:先将整个待排序序列分割成若干个子序列,将子序列排序,然后合并,此时序列已经基本有序,再进行一次直接插入排序。如下图:



首先整个待排序序列的分割:理论上间隔1<=d<=n都可,将相距为d的记录化为一组,将整个待排序序列分为d组(子序列),在子序列进行直接插入排序。(通常将d选n/2的下取整,然后迭代d/2)

重复分割直到d=1,即所有记录已经在一个序列中,并进行了一次直接插入排序。就可以到有序序列。

(二)交换排序(冒泡排序—>快速排序)

1、冒泡排序

冒泡排序通过两两比较相邻记录大小,反序交换位置,直到没有反序的记录为止。如图:



第一步:将待排序序列分为,有序序列和无序序列两个,初始有序序列记录是空,无序序列是整个待排序序列。

第二步:从序列第一个记录开始从头到尾比较相邻记录,如果是反序就交换,所以使得最值(最大值或者最小值)向后移动,进入有序序列。如上图第一趟排序就将最大值67移动到最后一个记录,作为第一个有序记录。

第三步:重复第二步直到无序序列记录为空或者所有无序序列中没有交换(这一步很重要,可以提前结束遍历,表示整个序列已经有序了)。

2、快速排序

快速排序是对冒泡排序的改进,基本思想是:首先选一个轴值,以此为分界,分为大于该值和小于该值的两部分,然后重复该操作,直到整个序列有序。如图:



上图表示以29为轴值将序列分为大于29和小于29的两个部分。

(三)选择排序(简单选择排序—>堆排序)

1、简单选择排序

基本思想是:第i躺排序,将无序列记录(整个序列第i个到第n个)中最值(最小或者最大值)选出来,放到整个序列第i个位置,序列的前i个记录即为有序的。如图:



第一步:将待排序序列分为有序和无序两部分,初始状态,无序为空,有序序列为整个待排序序列。

第二步:在无序区选取最值,并将它与无序区的第一个交换,同时将其纳入有序区,无序区记录减一。

第三步:重复第二步直到无序区只剩最后一个记录。

2、堆排序

堆排序是对简单选择排序的改进,利用堆的性质进行排序。基本思想:首先将待排序序列的记录构造成堆,取堆顶记录,即所有记录的最值,并将其移入有序区,将剩下的记录再构造成堆,这样又能找到此最值,一次类推,直到只剩一个记录。

补充:

堆:指的是具有以下性质的完全二叉树:每个节点的值都大于等于其左右孩子节点的值(大根堆)或者每个节点的值都小于等于其左右孩子节点的值(小根堆)。

当然还有:

(一)归并排序

归并排序:将若干有序序列逐步归并,最终归并为一个有序序列。我们常用的是二路归并排序,如图:



二路归并排序,将待排序每个记录看成有序序列,然后两两归并,直到合并为一个有序序列。

(二)桶排序

桶排序是一种简单的分配排序,它是基于均匀分布假设的,基本思想:假设待排序记录的值都在0~m-1之间,设置m个桶,将值为i的记录分配到第i个桶中,然后将各个桶的记录依次收集起来即可。如图:



上面假设待排序序列值为0~9然后将0~9分为10个桶,将待排序序列分别分配到10个桶中,然后依次收集含有记录的桶中的记录即可得到排序序列。桶可以用静态链表实现,而桶中重复的序列可以采用队列存储,所以桶排序是稳定排序。

(三)基数排序

基数排序排序的基本思想是:将关键码看成若干子关键码复合而成,然后借助分配和收集操作采用最次为优先的方法进行排序(还真没想好怎么解释。。。。。)。稳定排序算法。如图:



(四)计数排序

计数排序基本思想:对每个输入元素x,确定小于x的元素的个数。如图:



以上图为例:无序序列为:2、5、3、0、2、3、0、3。统计序列中记录值从小到大出现的累计次数。0出现两次所以将统计数组对于位置赋值为2,1出现0次2+0=2不变,2出现2次所以2+2=4,索引为2的位置的值被附为4,以此类推。最后输出统计数组中数值发生变化的数字,相邻变化差值为数字出现的次数。输出可得到有序序列。

排序算法性能比较

排序方法平均情况最好情况最坏情况辅助空间是否稳定
直接插入O(n2)O(n)O(n2)O(1)
希尔排序O(nlogn)~O(n2)O(n1.3)O(n2)O(1)
冒泡排序O(n2)O(n)O(n2)O(1)
快速排序O(nlogn)O(nlogn)O(n2)O(nlogn)~O(n )
简单选择O(n2)O(n2)O(n2)O(1)
堆排序O(nlogn)O(nlogn)O(nlogn)O(1)
归并排序O(nlogn)O(nlogn)O(nlogn)O(n)
基数排序O(d(n+m))O(d(n+m))O(d(n+m))O(m)
计数排序O(n)O(n)O(n)O(n+k)
桶排序O(n+m)O(n+m)O(n+m)O(m)

代码实现

直接插入排序

void insertion_sort(int r[], int n)//直接插入排序insertion
{
for (int i = 1; i < n; i++)
{
int temp = r[i];
int j;
for ( j = i-1; r[j] > temp;j--)
r[j + 1] = r[j];
r[j+1] = temp;
}
}
冒泡排序

void bubble_sort(int r[], int n) //冒泡排序bubble
{
int exchange = n;//设置标志,提前结束循环
for (int i = 0; i < n&&exchange != 0; i++)
{
exchange = 0;
for (int j = 0; j < n - i - 1; j++)
if (r[j] > r[j + 1])
{
int temp = r[j + 1];
r[j + 1] = r[j];
r[j] = temp;
exchange++;
}
}
}
简单选择排序

void select_sort(int r[], int n) //简单选择排序select
{
for (int i = 0; i < n; i++)
for (int j=0; j < n - i;j++)
if (r[n-i-1]<r[j])
{
int temp = r[j];
r[j] = r[n - i-1];
r[n - i-1] = temp;
}
}


希尔排序

void shell_sort(int r[], int n) //希尔排序shell
{
for (int d = n/2; d >= 1 ; d=d/2)
for (int i = d; i < n; i++)
{
int temp = r[i];
int j;
for (j = i - d; j >= 0 && r[j] > temp; j = j - d)
r[j + d] = r[j];
r[j + d] = temp;
}
}
快速排序
void quick_sort(int r[], int begin, int end) //快速排序quick
{
int partition(int r[], int begin, int end);
if (begin<end)
{
int i = partition(r, begin, end);
quick_sort(r, begin, i - 1);
quick_sort(r, i + 1, end);
}
}
int partition(int r[], int begin, int end)
{
int x = r[end];
int j = begin-1;
for (int i = begin; i <= end-1; i++)
{
if (r[i] <= x)
{
j++;
int temp = r[j];
r[j] = r[i];
r[i] = temp;
}
}
int tem = r[j+1];
r[j+1] = r[end];
r[end] = tem;
return j+1;
}

综合实现

#include<iostream>
//#include"stdlib.h"
using namespace std;
void main()
{
void insertion_sort(int r[],int n); //直接插入排序insertion
void shell_sort(int r[], int n);//希尔排序shell
void bubble_sort(int r[], int n);//冒泡排序bubble
void quick_sort(int r[], int begin, int end); //快速排序quick
void select_sort(int r[], int n);//简单选择排序select
cout << "直接插入排序..." << endl;//直接插入排序insertion
int a[10];
for (int i = 0; i < sizeof(a)/sizeof(int); i++)
a[i] = rand() % 9;
cout << "原有序列:" ;
for (int i = 0; i < sizeof(a) / sizeof(int); i++)
cout << a[i] << ",";
insertion_sort(a, sizeof(a) / sizeof(int));
cout << endl;
cout << "有序序列:" ;
for (int i = 0; i < sizeof(a) / sizeof(int); i++)
cout << a[i] << ",";
cout << endl;
//希尔排序shell
cout << "希尔排序..." << endl;
for (int i = 0; i < sizeof(a) / sizeof(int); i++)
a[i] = rand() % 9;
cout << "原有序列:";
for (int i = 0; i < sizeof(a) / sizeof(int); i++)
cout << a[i] << ",";
shell_sort(a, sizeof(a) / sizeof(int));
cout << endl;
cout << "有序序列:";
for (int i = 0; i < sizeof(a) / sizeof(int); i++)
cout << a[i] << ",";
cout << endl;
//冒泡排序bubble
cout << "冒泡排序..." << endl;
for (int i = 0; i < sizeof(a) / sizeof(int); i++)
a[i] = rand() % 9;
cout << "原有序列:";
for (int i = 0; i < sizeof(a) / sizeof(int); i++)
cout << a[i] << ",";
bubble_sort(a, sizeof(a) / sizeof(int));
cout << endl;
cout << "有序序列:";
for (int i = 0; i < sizeof(a) / sizeof(int); i++)
cout << a[i] << ",";
cout << endl;
//快速排序quick
cout << "快速排序..."
89cf
<< endl;
for (int i = 0; i < sizeof(a) / sizeof(int); i++)
a[i] = rand() % 9;
cout << "原有序列:";
for (int i = 0; i < sizeof(a) / sizeof(int); i++)
cout << a[i] << ",";
quick_sort(a,0, sizeof(a) / sizeof(int)-1);
cout << endl;
cout << "有序序列:";
for (int i = 0; i < sizeof(a) / sizeof(int); i++)
cout << a[i] << ",";
cout << endl;
//简单选择排序select
cout << "简单选择排序..." << endl;
for (int i = 0; i < sizeof(a) / sizeof(int); i++)
a[i] = rand() % 9;
cout << "原有序列:";
for (int i = 0; i < sizeof(a) / sizeof(int); i++)
cout << a[i] << ",";
select_sort(a, sizeof(a) / sizeof(int));
cout << endl;
cout << "有序序列:";
for (int i = 0; i < sizeof(a) / sizeof(int); i++)
cout << a[i] << ",";
cout << endl;
}
void insertion_sort(int r[], int n)//直接插入排序insertion { for (int i = 1; i < n; i++) { int temp = r[i]; int j; for ( j = i-1; r[j] > temp;j--) r[j + 1] = r[j]; r[j+1] = temp; } }
void shell_sort(int r[], int n) //希尔排序shell { for (int d = n/2; d >= 1 ; d=d/2) for (int i = d; i < n; i++) { int temp = r[i]; int j; for (j = i - d; j >= 0 && r[j] > temp; j = j - d) r[j + d] = r[j]; r[j + d] = temp; } }
void bubble_sort(int r[], int n) //冒泡排序bubble { int exchange = n;//设置标志,提前结束循环 for (int i = 0; i < n&&exchange != 0; i++) { exchange = 0; for (int j = 0; j < n - i - 1; j++) if (r[j] > r[j + 1]) { int temp = r[j + 1]; r[j + 1] = r[j]; r[j] = temp; exchange++; } } }
void quick_sort(int r[], int begin, int end) //快速排序quick { int partition(int r[], int begin, int end); if (begin<end) { int i = partition(r, begin, end); quick_sort(r, begin, i - 1); quick_sort(r, i + 1, end); } } int partition(int r[], int begin, int end) { int x = r[end]; int j = begin-1; for (int i = begin; i <= end-1; i++) { if (r[i] <= x) { j++; int temp = r[j]; r[j] = r[i]; r[i] = temp; } } int tem = r[j+1]; r[j+1] = r[end]; r[end] = tem; return j+1; }
void select_sort(int r[], int n) //简单选择排序select { for (int i = 0; i < n; i++) for (int j=0; j < n - i;j++) if (r[n-i-1]<r[j]) { int temp = r[j]; r[j] = r[n - i-1]; r[n - i-1] = temp; } }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: