堆排序
堆给人的感觉是一个二叉树,但是其本质是一种数组对象,因为对堆进行操作的时候将堆视为一颗完全二叉树,树种每个节点与数组中的存放该节点值的那个元素对应。所以堆又称为二叉堆,堆与完全二叉树的对应关系如下图所示:
把堆看成一个棵树,有如下的特性:
(1)含有n个元素的堆的高度是lgn。
(2)当用数组表示存储了n个元素的堆时,叶子节点的下标是n/2+1,n/2+2,……,n。
(3)在最大堆中,最大元素该子树的根上;在最小堆中,最小元素在该子树的根上。
(4)节点i 的左右子节点分别是 i * 2 + 1 和 i * 2 + 2。
堆排序
实现堆排序需解决两个问题:
1. 如何将n 个待排序的数建成堆;
2. 输出堆顶元素后,怎样调整剩余n-1 个元素,使其成为一个新堆。
堆的建立
堆的调整
算法实现
void heap_adjust(int *arr, int start, int end)
{
int temp = arr[start];
int pos;
for(pos = start * 2 + 1; pos <= end; pos = start * 2 + 1){
if(pos < end && arr[pos] < arr[pos +1])
++pos;//start -- parent;pos -- left; pos+1 -- right
if(arr[pos] < temp)//parent 和 较大的child比较
break;
arr[start] = arr[pos];
start = pos;
}
arr[start] = temp;
}
void heap_sort(int *arr, int size)
{
int i,temp;
printf("create heap:\n");
for( i = (size -1)/2; i>= 0; --i)
heap_adjust(arr,i,size - 1);
print(arr,size); //自底向上构造堆
printf("heap sort:\n");
for(i = size - 1; i > 0; --i){
temp = arr[i];
arr[i] = arr[0];
arr[0] = temp;
print(arr,size);
heap_adjust(arr,0,i - 1);
}
print(arr,size);
}
基数排序
是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。基数排序基于分别排序,分别收集,所以是稳定的。
int max_bit(int *arr, int size)
{
int bit,i,value,r = 10,count = 0;
for(bit = 0, i = 0; i < size; i++ ){
count = 0;
value = arr[i];
while(value){
value = value/r;
++count;
}
if(bit < count)
bit = count;
}
return bit;
}
void radix_sort(int *arr, int size)
{
int bits = max_bit(arr,size);
printf("max bit = %d\n",bits);
int count[10],temp[size];
int i,j,k,r = 1,value;
for(i = 0; i < bits; ++i){
for(j = 0; j < 10; ++j)
count[j] = 0;
for(j = 0; j < size; ++j){
value = arr[j] / r;
count[value % 10]++;
}
for(j = 1; j < 10; ++j){//计算位置
count[j] += count[j-1];
}
for(j = size - 1; j >= 0; --j){
value = arr[j] / r;//第一次遍历后需要
k = value % 10; //从后面到前面遍历,这样才保证有序
temp[count[k] - 1] = arr[j];
count[k]--;
}
for(j = 0; j < size; ++j)
arr[j] = temp[j];
r *= 10;
print(arr,size);
}
printf("\nresult: ");
print(arr,size);
}