为什么要排序
1. 有时应用本身就需要对信息进行排序。例如对财务报表进行排序
2. 很多算法通常把排序作为关键子程序,关键技术也体现在排序算法中
算法 | 最坏情况运行时间 | 平均情况/期望运行时间 |
插入排序 | O(n^2) | O(n^2) |
堆排序 | O(n lgn) | -- |
快速排序 | O(n^2) | O(n lgn) |
1. 插入排序
/*插入排序
p[] :待排序数组
len :待排序数组长度
*/
void insertSort(int p[],int len)
{
int i,pos,cur;
for (i = 1; i < len; i++)
{
pos = i -1 ; //有序序列的最后一个元素位置
cur = p[i]; //保存待排序元素的值
while ( pos >= 0 && p[pos] > cur) //如果cur值小于有序数组最后一个元素值,则后移有序
//数组,再检查前一个有序数组的值,重复以上循环,直到cur不大于有序数组的值
{
p[pos + 1] = p[pos];
pos--;
}
p[pos + 1] = cur; //将待排序元素插入数组中
}
}
2. 堆排序
#define INT_MAX 0x7FFFFFFF
#define INT_MIN (0-INT_MAX)
/*
最大堆排序
a[] :待排序数组
s : 父节点
len : 需要排序的堆长度
*/
void HeapAdjustMax(int a[],int s,int len)//一次筛选的过程
{
int max,tmp;
while(s <= len/2 -1)
{
tmp = (2 * s + 2 >= len) ? INT_MIN : a[2 * s + 2]; // 总数为偶数,最后一个父节点没有右孩子
max = (a[2 * s + 1] >= tmp) ? 2 * s + 1 : 2 * s + 2; // max 左右孩子中,最大的孩子值
if(a[max] > a[s]) //大堆小堆比较
{
tmp = a[max];
a[max] = a[s];
a[s] = tmp;
s = max; //交换父节点和子节点的值后,跟踪到子节点
}
else
break;
}
}
/*最小堆排序*/
void HeapAdjustMin(int a[],int s,int len)//一次筛选的过程
{
int min,tmp;
while(s <= len/2 -1)
{
tmp = (2 * s + 2 >= len) ? INT_MAX : a[2 * s + 2]; // 总数为偶数,最后一个父节点没有右孩子
min = (a[2 * s + 1] < tmp) ? 2 * s + 1 : 2 * s + 2; min 左右孩子中,最小的孩子值
if(a[min] < a[s]) //大堆小堆比较
{
tmp = a[min];
a[min] = a[s];
a[s] = tmp;
s = min; //交换父节点和子节点的值后,跟踪到子节点
}
else
break;
}
}
/*
a[] : 待排序数组
n : 数组长度
*/
void HeapSort(int a[],int n)
{
int temp,i;
/*n/2-1 为倒数第一个非叶子节点*/
for(i = n/2 - 1; i > 0;i--)//通过循环初始化顶堆,最后一个非叶子节点向前找
{
HeapAdjustMin(a,i,n); //HeapAdjustMax(a,i,n);
}
for(i = n;i > 1;i--) //末尾向前移动
{
HeapAdjustMin(a,0,i); //HeapAdjustMax(a,i,n);
temp=a[0];
a[0]=a[i-1];
a[i-1]=temp;//交换
}
}
3. 快速排序
/**************************快速排序法***********************************/
/*
a[] :待排序数组
left:左边界
right:右边界
*/
void quickSort(int a[],int left,int right)
{
int i = left;
int j = right;
int temp = a[left]; //此为基准数
if(left >= right)
return;
while(i != j)
{
while(i < j && a[j] >= temp) //从右向左,找到第一个大于基准数的值,标记
j--;
if(j > i)
a[i] = a[j]; //a[i]已经赋值给temp,所以直接将a[j]赋值给a[i],赋值完之后a[j],有空位
while(i<j && a[i]<=temp) //从左向右,找到一个小于基准的数,标记
i++;
if(i < j)
a[j] = a[i]; //交换,将待排序列以基准数分为左右两半,分治思想
}
a[i]=temp; //把基准插入,此时i与j已经相等R[low..pivotpos-1].keys≤R[pivotpos].key≤R[pivotpos+1..high].keys
quickSort(a,left,i-1); /*递归左边*/
quickSort(a,i+1,right); /*递归右边*/
}
测试程序
int main()
{
/* 插入排序*/
int num[] = {13, 7, 1, 8, 5, 12, 9,6};
int i;
int length = sizeof(num)/sizeof(num[0]);
// insertSort(num,length); //插入排序
// HeapSort(num,length); //堆排序
quickSort(num,0,length-1);
for(i=0;i < length;i++)
printf("%d\t",num[i]);
return 0;
}
本文只是算法的实现,具体参考《算法导论》