堆排序
堆排序是对选择排序的改进 时间复杂度是 O(nlogn),大概思路是:
- 将待排序的数列构造成大顶堆或者小顶堆 大顶堆就是每个结点的值大于左右孩子的值
- 此时,整个数列的最大值就是堆顶的根节点(将其与末尾交换)
- 然后将剩余的n-1个序列重新构造成一个堆
- 反复进行
上代码:
/*
============================================================================
Name : HeapSort.c
Author : liuxin
Version :
Copyright : Your copyright notice
Description : Hello World in C, Ansi-style
============================================================================
*/
#include<stdio.h>
void swap(int a[],int i,int j)
{
int temp;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
void HeapAdjust(int a[],int s,int n)
{
int i,temp;
temp = a[s]; //temp存放双亲结点
for(i=2*s;i<=n;i=i*2) //2*s代表左结点
{
if(i<n && a[i]<a[i+1]) //i+1代表右结点
{
i++;
}
if(temp>a[i])
{
break;
}
a[s] = a[i];
s = i;
}
a[s] = temp;
}
void HeapSort(int a[],int n)
{
int i;
for(i=n/2;i>0;i--)
{
HeapAdjust(a,i,n); //构建大顶堆,其中i是双亲结点,n是总个数
}
for(i=1;i<9;i++) //把第一次构建出来的大顶堆打印出来了
{
printf("%d ",a[i]);
}
printf("\n");
for(i=n;i>1;i--)
{
swap(a,1,i); //构建完大顶堆之后,第一个元素是最大的了,把他和最后的互换,然后在重新把剩下的构建大顶堆
HeapAdjust(a,1,i-1); //重新从第一个顶点开始构建
}
}
int main()
{
int i;
int a[]={-1,1,3,2,6,5,4,8,7}; //从第一个元素开始排,因为这样正好2*i是左结点,2*i+1是右结点
HeapSort(a,8);
for(i=1;i<9;i++)
{
printf("%d ",a[i]);
}
return 0;
}
归并排序
归并排序(Merge Sort)就是利用归并思想实现的排序算法,他的原理是假设初始序列有n个元素,可以看成有n个有序的子序列,每个子序列的长度是1,然后归并,得到n/2个长度为2或者1的子序列,然后再两辆归并,反复如此,直到得到一个长度为n的有序序列位置。上图:
递归实现代码:
#include<stdio.h>
#define MAXSIZE 8
void merging(int *list1,int list1_size,int *list2,int list2_size) //给两个数组排序然后放一起放在list1中
{
int i,j,k,m;
i=j=k=0;
int temp[MAXSIZE];
while(i < list1_size && j < list2_size)
{
if(list1[i]<list2[j])
{
temp[k++] = list1[i++];
}
else
{
temp[k++] = list2[j++];
}
}
while(i < list1_size)
{
temp[k++] = list1[i++];
}
while(j < list2_size)
{
temp[k++] = list2[j++];
}
for(m = 0;m < (list1_size+list2_size);m++)
{
list1[m]=temp[m];
}
}
void MergeSort(int a[],int n) //递归实现
{
if(n>1)
{
int *list1 = a;
int list1_size = n/2;
int *list2 = a+n/2;
int list2_size = n - list1_size;
MergeSort(list1,list1_size);
MergeSort(list2,list2_size);
merging(list1,list1_size,list2,list2_size);
}
}
int main()
{
int a[]={5,2,9,1,4,7,8,3};
int i;
MergeSort(a,8);
for(i=0;i<8;i++)
{
printf("%d ",a[i]);
}
return 0;
}
把这两个排序算法放在一起写是因为这两个排序算法无论是在最坏情况,最好情况,平均情况下时间复杂度都是O(nlogn),都是十分好的排序算法,则两个相比而言,归并排序稳定,堆排序不稳定。