1、冒泡排序:
冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,则不需要交换,所以冒泡排序是一种稳定的排序算法。
稳定的排序算法
冒泡排序平均时间复杂度:O(n^2)
c代码:
int baseData[] = {9, 10, 78, 76, 1, 100, 35, 56, 20, 39, 70, 56, 27};
int length = sizeof(baseData)/sizeof(int);
for(int i = 0; i < length - 1; i++){
for(int j = 0; j < length - i - 1; j++){
if (baseData[j] > baseData[j + 1]) {
int temp = baseData[j];
baseData[j] = baseData[j+1];
baseData[j+1] = temp;
}
}
}
for (int m = 0; m < length; m++) {
printf("%3d\n", baseData[m]);
}
输出:
1
9
10
20
27
35
39
56
56
70
76
78
100
Program ended with exit code: 0
2、鸡尾酒排序(即双向冒泡排序)
稳定的排序算法
鸡尾酒排序平均时间复杂度:O(n^2)
排序过程如图:
c代码:
int baseData[] = {9, 10, 78, 76, 1, 100, 35, 56, 20, 39, 70, 56, 27};
int length = sizeof(baseData)/sizeof(int);
for(int i = 0; i < length/2; i++){
for(int j = i; j < length - i - 1; j++){
if (baseData[j] < baseData[j + 1]) {
int temp = baseData[j];
baseData[j] = baseData[j+1];
baseData[j+1] = temp;
}
}
for(int j = length - i - 1 - 1; j > i; j--){
if (baseData[j] > baseData[j-1]) {
int temp = baseData[j];
baseData[j] = baseData[j-1];
baseData[j-1] = temp;
}
}
}
for (int m = 0; m < length; m++) {
printf("%3d\n", baseData[m]);
}
输出:
100
78
76
70
56
56
39
35
27
20
10
9
1
Program ended with exit code: 0
3、直接插入排序
直接插入排序:把待排序的纪录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的纪录插入完为止,得到一个新的有序序列,实际操作是将数组分为两部分,一部分是排好序的部分,另一部分是待排序的部分,将待排序的部分逐个插入排好序的部分,插入时数组元素需要移动
稳定的排序算法
直接插入排序的时间复杂度:O(n^2)
c代码:
int baseData[] = {9, 10, 78, 76, 1, 100, 35, 56, 20, 39, 70, 56, 27};
int length = sizeof(baseData)/sizeof(int);
//从小到大排列
for (int i = 1; i < length; i++) {
int sign = 0;
int temp = baseData[i];
for (int j = 0; j < i; j++) {
if (temp < baseData[j]) {
sign = j;
break;
}else{
sign = i;
}
}
for (int j = i; j > sign; j--) {
baseData[j] = baseData[j-1];
}
baseData[sign] = temp;
}
for (int m = 0; m < length; m++) {
printf("%3d\n", baseData[m]);
}
输出:
1
9
10
20
27
35
39
56
56
70
76
78
100
Program ended with exit code: 0
4、希尔排序
希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
不稳定的排序算法
c代码:
//希尔排序
int increment = length;
while(1)
{
increment = increment/2;
for(int x=0; x < increment; x++)
{
for(int i = x + increment; i < length; i = i + increment)
{
int temp=baseData[i];
int j;
for(j = i-increment; j >= 0 && baseData[j] > temp; j = j - increment)
{
baseData[j+increment] = baseData[j];
}
baseData[j+increment] = temp;
}
}
if(increment == 1)
{
break;
}
}
for (int m = 0; m < length; m++) {
printf("%3d\n", baseData[m]);
}
输出同上
5、快速排序
设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。
不稳定的排序算法
排序过程如图:
c代码:
void sort(int *temp, int left, int right)
{
if(left >= right)/*如果左边索引大于或者等于右边的索引就代表已经整理完成一个组了*/
{
return ;
}
int i = left;
int j = right;
int key = temp[left];
while(i < j) /*控制在当组内寻找一遍*/
{
while(i < j && key <= temp[j])
/*而寻找结束的条件就是,
1,找到一个小于或者大于key的数(大于或小于取决于你想升序还是降序)
2,没有符合条件1的,并且i与j的大小没有反转
*/
{
j--;/*向前寻找*/
}
temp[i] = temp[j];
/*找到一个这样的数后就把它赋给前面的被拿走的i的值(如果第一次循环且key是temp[left],那么就是给key)*/
while(i < j && key >= temp[i])
/*这是i在当组内向前寻找,同上,不过注意与key的大小关系停止循环和上面相反,因为排序思想是把数往两边扔,所以左右两边的数大小与key的关系相反*/
{
i++;
}
temp[j] = temp[i];
}
temp[i] = key;/*当在当组内找完一遍以后就把中间数key回归*/
sort(temp, left, i - 1);/*最后用同样的方式对分出来的左边的小组进行同上的做法*/
sort(temp, i + 1, right);/*用同样的方式对分出来的右边的小组进行同上的做法*/
/*当然最后可能会出现很多分左右,直到每一组的i = j 为止*/
}
//快速排序
sort(baseData, 0, length - 1);
for (int m = 0; m < length; m++) {
printf("%3d\n", baseData[m]);
}
输出同上
6、简单选择排序
每次找到剩余部分最小值,与第i个进行交换
不稳定排序算法
c代码:
//简单选择排序
int m = 0;
for(int i = 0; i < length - 1; i++){
m = i;
for (int j = i+1; j < length; j++) {
if (baseData[m] > baseData[j]) {
m = j;
}
}
if (m != i) {
int temp = baseData[m];
baseData[m] = baseData[i];
baseData[i] = temp;
}
}
for (int m = 0; m < length; m++) {
printf("%3d\n", baseData[m]);
}
输出同上
7、堆排序
堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。
注意
特点
(参考:http://baike.baidu.com/link?url=3-gL9GHfLbboDeMu6uX3reuQ90IaAa-zpbatNmSDLOeQkdg771U5cu2JlM3GwWsPOAJFbbiwINV6xgSCWwwxNK)
c代码
//array是待调整的堆数组,i是待调整的数组元素的位置,nlength是数组的长度
//本函数功能是:根据数组array构建大根堆
void HeapAdjust(int array[],int i,int nLength)
{
int nChild;
int nTemp;
for(;2*i+1<nLength;i=nChild)
{
//子结点的位置=2*(父结点位置)+1
nChild=2*i+1;
//得到子结点中较大的结点
if(nChild<nLength-1&&array[nChild+1]>array[nChild])++nChild;
//如果较大的子结点大于父结点那么把较大的子结点往上移动,替换它的父结点
if(array[i]<array[nChild])
{
nTemp=array[i];
array[i]=array[nChild];
array[nChild]=nTemp;
}
else break; //否则退出循环
}
}
//堆排序算法
void HeapSort(int array[],int length)
{
int i;
//调整序列的前半部分元素,调整完之后第一个元素是序列的最大的元素
//length/2-1是最后一个非叶节点,此处"/"为整除
for(i=length/2-1;i>=0;--i)
HeapAdjust(array,i,length);
//从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素
for(i=length-1;i>0;--i)
{
//把第一个元素和当前的最后一个元素交换,
//保证当前的最后一个位置的元素都是在现在的这个序列之中最大的
array[i]=array[0]^array[i];
array[0]=array[0]^array[i];
array[i]=array[0]^array[i];
//不断缩小调整heap的范围,每一次调整完毕保证第一个元素是当前序列的最大值
HeapAdjust(array,0,i);
}
}
//堆排序
HeapSort(baseData, length);
for (int m = 0; m < length; m++) {
printf("%3d\n", baseData[m]);
}
输出同上