排序和顺序统计学——堆排序

本文介绍了堆数据结构及其在实现优先级队列中的应用。首先详细解释了堆的定义和性质,接着给出了堆排序算法的具体实现。最后,探讨了如何使用堆结构实现基本的优先级队列操作。
一、堆
    堆结构是一种数组对象,可以被视为一棵完全二叉树。数中每个节点与数组中存放该点中值的那个元素对应。表示一个堆的数组具有两个属性:
length[A]:数组中的元素个数
heap_size[A]:存放在A中的堆的元素个数。
树的根为A[1],给定某个节点的下标i,其父结点PARENT(i),左儿子LEFT(i),右儿子RIGHT(i)。
堆结构还满足堆性质(最大堆):对除根以外的每个节点i,
       A[PARENT(i)] >= A[i]
Heapfy:维持堆性质,O(lgn)时间;
BuildHeap:从无序的输入数组中构造出一个堆来,O(1)时间;
HeapSort:对数组进行排序,O(nlgn)时间;
ExtractMax和Insert:使堆结构可以作为一个优先级队列来用,O(lgn)时间。


二、优先级队列
优先级队列是一种用来维护由一组元素构成的集合S的数据结构,这一组元素中的每一个都有个关键字Key。作用于优先级队列上的操作有:
Insert(S, x)
Maximum(S)
ExtractMax(S)
IncreaseKey(S, x, k)

/*
 *Copyright(c) 2008 All rights reserved.
 *
 *Heap Sort
 *Author:Greentea
 *Date:01.20
 
*/

#include 
<stdio.h>
#include 
<assert.h>
#include 
<limits.h>
#define PARENT(i) ((i-1)>>1)    /*节点i的父结点*/
#define LEFT(i) ((i<<1)+1)        /*节点i的左孩子*/
#define RIGHT(i) ((i<<1)+2)        /*节点i的右孩子*/

void exchange(int *a, int *b);
void MaxHeapify(int *a, int i, int heapSize);
void BuildMaxHeap(int *a, int heapSize);
void HeapSort(int *a, int heapSize);
void HeapIncreaseKey(int *a, int i, int key);
void MaxHeapInsert(int *a, int heapSize, int key);
int HeapMaximum(int *a);
int HeapExtractMax(int *a, int heapSize);

/*
 *交换a和b指向的值
 
*/

void exchange(int *a, int *b)
{
    
int temp;
    temp 
= *a;
    
*= *b;
    
*= temp;
}


/*
 *Input:a:数组
 *        i:下标
 *        heapSize:数组大小
 *pre:  该函数调用时,LEFT(i)和RIGHT(i)为根的两棵子树都已是堆
 *post: 以i为根的子树成为一个堆
 
*/

void MaxHeapify(int *a, int i, int heapSize)
{
    
int L, R;
    
int largest;

    L 
= LEFT(i);
    R 
= RIGHT(i);
    
if(L < heapSize && a[L] > a[i])
        largest 
= L;
    
else
        largest 
= i;
    
if(R < heapSize && a[R] > a[largest])
        largest 
= R;
    
if(largest != i)
    
{
        exchange(
&a[i], &a[largest]);
        MaxHeapify(a, largest, heapSize);
    }

}

/*
 *自底向上地用Heapify来讲一个数组a[0...n](n=heapSize-1)变成一个堆
 *Input:a:数组
 *        heapSize:数组大小
 
*/

void BuildMaxHeap(int *a, int heapSize)
{
    
int i;

    
for(i = PARENT(heapSize); i >= 0; i--)
        MaxHeapify(a, i, heapSize);
}


/*
 *Input:a:数组
 *        heapSize:数组大小
 *调用BuildHeap将输入数组a[0...n]构造成一个堆,因数组中最大元素
 *是在根a[0]上,则可通过把它与a[n]互换来达到最终的正确位置,再将
 *a[0...n-1],通过Heapify函数调整,继续上面过程,直到堆的大小从n-1
 *变为1为止
 
*/

void HeapSort(int *a, int heapSize)
{
    
int i;

    BuildMaxHeap(a, heapSize);
    
for(i = heapSize - 1; i > 0; i--)
    
{
        exchange(
&a[0], &a[i]);
        heapSize
--;
        MaxHeapify(a, 
0, heapSize);
    }

}


/*实例*/
int main(int argc, char **argv)
{
    
int i, heapSize;
    
int a[10]={2638971405};

    heapSize 
= 10;
    HeapSort(a, heapSize);
    
for(i=0; i<10; i++)
    
{
        printf(
"%d ", a[i]);
    }

    printf(
" ");

    
return 0;
}


/******************************************************************
 *优先级队列操作
 *HeapMaximum:返回堆的最大元素
 *HeapExtractMax:删除堆的最大元,并调整重建堆
 *HeapIncreaseKey:堆中某元素值增加,并调整重建堆
 *MaxHeapInsert:将一个节点插入到堆中
 *****************************************************************
*/

int HeapMaximum(int *a)
{
    
return a[0];
}


int HeapExtractMax(int *a, int heapSize)
{
    
int max;

    assert(heapSize
>=1);
    max 
= a[0];
    a[
0= a[heapSize-1];
    heapSize
--;
    MaxHeapify(a, 
0, heapSize);

    
return max;
}


void HeapIncreaseKey(int *a, int i, int key)
{
    assert(key 
>= a[i]);
    a[i] 
= key;
    
while((i > 0&& (a[PARENT(i)] < a[i]))
    
{
        exchange(
&a[PARENT(i)], &a[i]);
        i 
= PARENT(i);
    }

}


void MaxHeapInsert(int *a, int heapSize, int key)
{
    heapSize
++;
    a[heapSize
-1= INT_MIN;
    HeapIncreaseKey(a, heapSize
-1, key);
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值