算法基础6:堆排序算法

参考《算法导论》P84~P90,注意,数组下标从1开始。

#include 
#include 
#define MAXSIZE 100
void heapSort(int a[], int heapSize); // 堆排序
void maxHeapify(int a[], int i, int heapSize); // 维护以i为根节点的最大堆的性质
void buildMaxHeap(int a[], int heapSize); // 建最大堆
int getLeft(int i); // 获得左子树跟节点的下标
int getRight(int i); // 获得右子树跟节点的下标
void swap(int* a, int* b);
int readSeq(int a[]); // 读入一个整数序列,返回读入的整数的个数,下标从1开始
void showSeq(int a[], int n);

int main()
{
    int n, nums[MAXSIZE];
    while ((n = readSeq(nums)) > 0) // 如果输入的序列长度大于零就执行排序,否则退出
    {
        showSeq(nums, n);
        heapSort(nums, n);
        showSeq(nums, n);
    }
    return 0;
}

void swap(int* a, int* b)
{
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

int getLeft(int i)
{
    return i * 2;
}

int getRight(int i)
{
    return i * 2 + 1;
}

void heapSort(int a[], int heapSize) // 堆排序
{
    buildMaxHeap(a, heapSize);
    while (heapSize >= 2)
    {
        swap(&a[1], &a[heapSize]);
        heapSize--;
        maxHeapify(a, 1, heapSize);
    }
}

void buildMaxHeap(int a[], int heapSize) // 建最大堆
{
    int i = heapSize / 2; // 最后一个父节点的下标
    while (i >= 1)
    {
        maxHeapify(a, i, heapSize);
        i--;
    }
}

void maxHeapify(int a[], int i, int heapSize) // 维护以i为根节点的最大堆的性质
{
    int lIndex = getLeft(i);
    int rIndex = getRight(i);
    int largest;
    if (lIndex <= heapSize && a[lIndex] > a[i])
        largest = lIndex;
    else
        largest = i;
    if (rIndex <= heapSize && a[rIndex] > a[largest])
        largest = rIndex;
    if (largest != i)
    {
        swap(&a[largest], &a[i]); // 将最大的置于堆顶
        maxHeapify(a, largest, heapSize); // 注意:此时a[largest]是原来的a[i]
    }
}

int readSeq(int a[]) // 读入序列
{
    int n, i = 1; // 从下标为1的地方开始存,a[0]不使用
    scanf("%d", &n);
    while (i <= n)
        scanf("%d", &a[i++]);
    return i - 1; // 返回读入元素的个数
}

void showSeq(int a[], int n)
{
    int i = 1;
    while (i <= n)
        printf("%d ", a[i++]);
    putchar('\n');
}

你可能感兴趣的:(算法&数据结构)