排序算法(C语言实现)
本文共介绍了7种排序算法
参考文章:
https://blog.csdn.net/weixin_44811417/article/details/90748011
https://www.cnblogs.com/onepixel/articles/7674659.html
1.冒泡排序
1.1 基本思想:依次向后两两相邻比较,大的向后移
1.2 代码示例
void bubbleSort(int *a,int n)
{
int i,j,tmp;
for(i=0;i<n-1;i++) //排序总次数,最后一次不需要排序已经是最大值
{
for(j=0;j<n-1-i;j++) //每次排序次数:已排过不参加排序,排序总次数-i
{
if(a[j] > a[j+1]) //交换
{
tmp = a[j];
a[j] = a[j+1];
a[j+1] = tmp;
}
}
}
}
2.选择排序
2.1 基本思想:从无序队列中选择最小值,放置到有序队列的末尾
2.2 代码示例
void selectSort(int *a,int n)
{
int i,j,tmp,minIndex;
for(i=0;i<n-1;i++) //排序总次数,最后一次不需要排序已经是最大值
{
minIndex = i; //最小序号初始位置
for(j=i+1;j<n;j++) //从初始位置向后开始找,找到最小元素位置
{
if(a[j] < a[minIndex])
{
minIndex = j;
}
}
tmp = a[minIndex]; //将找到的值放置在有序队列末尾
a[minIndex] = a[i];
a[i] = tmp;
}
}
3.插入排序
3.1 基本思想:根据值大小插入到前面有序队列中
3.2 代码示例
void insertSort(int *a,int n)
{
int i,j,tmp;
for(i=1;i<n;i++) //排序次数,第一个元素默认有序
{
tmp=a[i];
j=i-1;
while((j>=0) && (a[j]>tmp)) //为插入元素腾出空间
{
a[j+1]=a[j];
j--;
}
a[j+1]=tmp; //插入
}
}
4.希尔排序
4.1 基本思想:插入排序的优化,增量为2x或3x+1
4.2 代码示例
void shellSort(int *a,int n)
{
int i,j,h,tmp;
h=1;
while(h<n/3)
{
h=h*3+1; //增量初始值
}
while(h) //对每个增量进行插入排序
{
for(i=h;i<n;i++)
{
tmp = a[i];
j=i-h;
while((j>=0) && (a[j]>tmp))
{
a[j+h] = a[j];
j-=h;
}
a[j+h] = tmp;
}
h=h/3;
}
}
5.快速排序
5.1 基本思想:分而治之,根据基准值将队列分成两个部分,一部分小于基准值,一部分大于基准值,然后分别递归这两个部分
5.2 代码示例
int getKey(int *a,int left,int right)
{
int key;
key=a[left];
while(left < right)
{
while((left<right) && (a[right]>=key)) //从后往前找,找到小于基准值的位置
{
right--;
}
a[left]=a[right];
while((left<right) && (a[left]<=key)) //从前往后找,找到大于基准值的位置
{
left++;
}
a[right]=a[left];
}
a[left]=key; //查找完毕left=right,放入基准值,返回基准值所在位置
return left;
}
void quickSort(int *a,int left,int right)
{
int index;
if(left < right)
{
index = getKey(a,left,right);
quickSort(a,left,index-1);
quickSort(a,index+1,right);
}
}
6.归并排序
6.1 基本思想:分而治之,将序列拆分成多个子序列,使每个子序列有序
6.2 代码示例
void merge(int *a,int left,int right,int mid)
{
int *b,low,high,cnt=0,i,n;
n=right-left+1;
b=(int *)malloc(sizeof(int)*n);
low = left;
high = mid+1;
while((low<=mid) && (high<=right)) //归并
{
b[cnt++] = ((a[low]<a[high]?a[low++]:a[high++]));
}
//有剩余
while(low<=mid)
{
b[cnt++] = a[low++];
}
while(high<=right)
{
b[cnt++] = a[high++];
}
//排序后的复制到原数组
for(i=0;i<n;i++)
{
a[left+i] = b[i];
}
free(b);
}
6.2.1 递归方法
void mergeSort(int *a,int left,int right)
{
int mid;
if(left < right)
{
mid = (right+left)/2;
mergeSort(a,left,mid);
mergeSort(a,mid+1,right);
merge(a,left,right,mid);
}
}
6.2.1 非递归
void unRecursive(int *a,int n)
{
int i,j,len,left,right,mid;
len = 1; //len=mid-left+1
while(len < n)
{
for(i=0;(i+len)<n;i+=len*2)
{
left = i;
mid = i+len-1;
right = i+len*2-1;
if(right > n-1)
{
right = n-1;
}
merge(a,left,right,mid);
}
len=len*2;
}
}
7.堆排序
7.1 基本思想:每个父节点的值大于它的子节点值,移除根节点,重新构建堆结构
7.2 相关知识
堆排序的堆结构是一个完全二叉树结构;
//完美二叉树:除了叶子节点外的每个节点都有两个孩子
//完全二叉树:除了最后一层外其他每层都被完全填充,并所有节点保持左对齐
//完满二叉树:每一层都被完全填充
//完全二叉树节点关系:父节点k,左节点2k+1,右节点2k+2(k从0开始)
推导:
7.3 代码示例
void sink(int *a,int n,int k)
{
int left,tmp;
while((left=2*k+1) < n)
{
if(left+1 < n) //存在右节点,选用值大的节点
{
left=(a[left]>a[left+1])?left:left+1;
}
if(a[left] < a[k]) //子节点小于根节点值,不需要继续排序,退出
{
break;
}
else //子节点大与根节点值,交换;
{
tmp = a[k];
a[k] = a[left];
a[left] = tmp;
}
k = left; //对子节点继续比较
}
}
void heapSort(int *a,int n)
{
int k,tmp;
//构建堆
for(k=n/2-1;k>=0;k--)
{
sink(a,n,k);
}
//移除根节点,重新构建堆
while(n>0)
{
tmp = a[0];
a[0] = a[n-1];
a[n-1] = tmp;
n--;
sink(a,n,0);
}
}