说明
此代码文件包含排序类型:冒泡、选择、插入、shell、快速。
代码
/*
** sort create by yubo.wang 2018.9.13
** 此文件包含排序类型:冒泡、选择、插入、shell、快速。
*/
#include <stdio.h>
#include <string.h>
/* 冒泡排序
* 通过无序区中相邻记录关键字间的比较和位置交换,使最小的关键字记录如气泡一样逐渐漂浮至水面
* 时间复杂度O(n²)
* 稳定
*/
/*
** 第1种:每一轮从前面往最后比较相邻把最大的往后面推
*/
int sort_bubble_1(int string[],int len)
{
int i;
int j;
int tmp;
for(i=1; i<len; i++)//i记录找到最大元素个数,最小的元素没有被记录是因为最后被交换到最前
{
for(j=0; j<len-i; j++)//从前面往最后比较相邻把最大的往后面推
{
if(string[j]>string[j+1])
{
tmp = string[j];
string[j] = string[j+1];
string[j+1] = tmp;
}
}
}
return 0;
}
/*
** 第2种:每一轮从从最后往前面比较相邻把最小的往前面推,并记录交换标志
*/
int sort_bubble_2(int string[],int len)
{
int i,j,exchange;
int tmp;
for(i=0; i<len-1; i++)
{
exchange=0;
for(j=len-1; j>i; j--)//从最后往前面比较相邻把最小的往前面推
{
if(string[j] < string[j-1])//后面的比前面元素小,就交换
{
tmp = string[j];
string[j] = string[j-1];
string[j-1] = tmp;
exchange=1;
}
}
if(0 == exchange)//本趟没有发生交换,说明已经有序所以退出
{
return 0;
}
}
return 0;
}
/* 选择排序
* 每步从待排序的记录中选出最小的记录,顺序放在已排序的记录序列的最前,直到全部排序完成。
* 时间复杂度O(n²)
* 不稳定,元素位置改变
*/
/*
** 第1种:每一轮找到比前面小的元素只进行记录不进行交换,找完后再进行交换。找到最小的放在第一位
*/
int sort_select_1(int string[],int len)
{
int i;
int j;
int min;
int temp;
for(i = 0; i < len-1; i++)
{
min = i;//记录当前比较基准编号
for(j=i+1; j<len; j++)//后面与这个min编号的比较
{
if(string[j]<string[min])
{
min=j;//用min指出每趟在无序区段的最小元素
}
}
temp = string[i];//这一趟找到了最小的元素与基准编号交换
string[i] = string[min];
string[min] = temp;
}
return 0;
}
/*
** 第2种:每一轮中每一次找到比前面小的元素就进行交换。把最大的一直推到最后
*/
int sort_select_2(int string[],int len)
{
int i;
int j;
int min;
int temp;
for(i=0; i<len-1; i++)
{
min = i;
for(j=i+1; j<len; j++)
{
if(string[j]<string[min])
{
temp = string[i];
string[i] = string[j];
string[j] = temp;
}
}
}
return 0;
}
/*
* 直接插入排序
* 将前面排好序,后面的从后面以此比较插入到前面有序的数组里面,像打扑克牌齐牌时一样拿出一张往前插入有序的数组中
* 时间复杂度O(n²)
* 稳定,元素位置不变
*/
/*
** 第1种:从前面往后,记录后面要插入的元素,找到准确的位置再插入
*/
int sort_insert_1(int string[],int len)
{
int i;
int j;
int temp;
for(i=1; i<len; i++)
{
temp = string[i];//先记录要往前面插入的元素,因为后面会覆盖掉
j=i-1;
while(j>=0 && string[j]>temp)//把大与temp元素的进行后移一位覆盖掉temp元素,以便腾出一个位置插入temp
{
string[j+1]=string[j];
j--;
}
string[j+1]=temp;//说明temp找到了准确的位置并开始插入
}
return 0;
}
/*
** 第2种:从前面往后,一直往前比较相邻,前面的大于后面就交换
*/
int sort_insert_2(int string[],int len)
{
int i;
int j;
int temp;
for(i=1; i<len; i++)
{
temp = string[i];//先记录要往前面插入的元素,因为后面会覆盖掉
for(j=i-1; j>=0 && string[j]>temp; j--)//一直往前比较相邻,前面的大于后面就交换,
{
string[j+1] = string[j];
string[j] = temp;
}
}
return 0;
}
/*
* shell排序
* 把记录按下标的一定增量d分组,对每组记录采用直接插入排序方法进行排序,随着增量逐渐减小,所分成的组包含的记录越来越多,
* 到增量减小到为1时,整个数据合成一组,构成一组有序记录。
* 时间复杂度O(nlog₂n)
*
*/
int sort_shell_1(int string[],int n)
{
int gap;
int i;
int j;
int temp;
for(gap = n/2; gap > 0; gap /=2)
{
for(i = gap; i < n; i++)
{
for(j = i-gap; (j>=0)&&(string[j]>string[j+gap]); j-=gap)
{
temp = string[j];
string[j] = string[j+gap];
string[j+gap] = temp;
}
}
}
return 0;
}
int sort_shell_2(int string[],int n)
{
int gap;
int i;
int j;
int temp;
gap = n/2;//增量置初值
while(gap > 0)
{
for(i = gap; i < n; i++)//对所有相隔gap位置的元素组进行排序
{
temp = string[i];
j = i-gap;
while(j>=0 && temp<string[j])//对相隔gap位置的元素组进行排序
{
string[j+gap] = string[j];
j=j-gap;//移到本组的前一个元素
}
string[j+gap] = temp;
j=j-gap;
}
gap /=2;//减小增量
}
return 0;
}
/* 快速排序
* 由冒泡排序改进而来,在待排序的n个记录中任取一个记录(通常取第一个记录),把该记录放入最终位置后,
整个数据区间被此记录分割成两个子区间,比该记录小的放在前子区间,比它大的放在后子区间,并把该记录
排在这两个子区间的中间,这个过程称作一趟快速排序。
* 时间复杂度
* 稳定?
*/
void sort_quick(int string[],int s,int len)
{
int i=s,j=len;
int tmp;
if(s<len)//区间内至少存在一个元素的情况
{
tmp=string[s];//用区间的第1个记录作为基准
while(i!=j)//从区间两端交替向中间扫描,直到i=j为止
{
while(j>i && string[j]>tmp)
j--;//从右向左扫描,找到第一个关键字小于tmp的string[j]
string[i]=string[j];//找到这样的string[j],则与string[i]交换
while(i<j && string[i]<tmp)
i++;//从左向右扫描,找到第一个关键字大于tmp的string[i]
string[j]=string[i];//找到这样的string[i],则与string[j]交换
}
string[i]=tmp;
sort_quick(string, s, i-1);//对左区间递归排序
sort_quick(string, i+1, len);//对右区间递归排序
}
}
int main(void)
{
int i = 0;
int string[] = {4,3,2,1};
int len = sizeof(string)/sizeof(int);
printf("len=%d\n",len);
sort_quick(string, 0, len);
for(i=0; i<len; i++)
{
printf("%d ", string[i]);
}
printf("\n");
return 0;
}
/* 归并排序
*
*
*
*/
/* 基数排序
*
*
*
*/
/* 堆排序
*
*
*
*/