C语言实现常用数据结构——堆

#include<stdio.h>
#include<stdlib.h>
#define CAPACITY 20

/*堆有两个性质:
 * 1.结构性:堆必须是一颗完全二叉树
 * 2.堆序性:堆的父节点要么都大于子节点,要么小于子节点,前者叫大顶堆,后者叫小顶堆;
 * 由此,堆可以用一个数组来表示,并有如下性质:
 * 1.对于任意i位置的元素,他的左子节点在2i位置,右子节点在2i+1位置(前提是根节点下标从1开始,如果从0开始则是<2i+1,2i+2>);
 * 2.他的父节点(假如有)在i/2位置*/

/*创建一个小顶堆,size代表的是实际元素的个数*/
typedef struct MinHeap {
    int size;
    int data[CAPACITY];
} heap;

void init( heap *h );
void insert(heap *h,int x);
void travel(heap *h);

/*数组0位置要空着*/
void init( heap *h ) {
    h->size=0;
}

void insert(heap *h,int x) {
    if(h->size == CAPACITY) {
        printf("heap is full!");
        return;
    }
    int i;
    h->size++;
    for(i=h->size; i>=1; i/=2) {
        if(x < h->data[i/2]) {
            h->data[i]=h->data[i/2];
        } else {
            break;
        }
    }
    h->data[i]=x;
}
/*删除最小元素,在小顶堆即意味着删除根节点
 * 1.首先将根元素保存,等待最后return;
 * 2.将最后一个元素赋值给根元素,并将这个值赋给缓冲区,这样保证了堆的结构性;
 * 3.从根节点开始遍历,比较父节点和两个子节点的大小,如果缓冲区值大于较小的子节点,则将小节点的值赋给父节点
 * 4.直到缓冲区值小于游标的两个子节点,此时将缓冲区值赋给游标所在位置*/
int deleteMin(heap *h) {
    int child;
    int result=h->data[1];
    h->data[1]=h->data[h->size];
    h->size--;
    int i=1;
    int temp=h->data[1];
    for(i=1; 2*i <= h->size; i=child) {
        child=2*i;
        if(child !=h->size && h->data[child] > h->data[child+1] ) {/*如果左子节点非最后元素且>右子节点,则右子节点最小*/
            child++;
        }
        if(temp > h->data[child]) {/*如果temp大于当前元素的最小子节点,则将最小子节点赋值给父节点,否则跳出*/
            h->data[i]=h->data[child];
        } else {
            break;
        }
    }
    h->data[i]=temp;/*将缓冲区值赋给当前游标*/
    return result;
}

/*遍历堆数组:越过空白位置0,从1开始*/
void travel(heap *h) {
    int i;
    for(i=1; i<=h->size; i++) {
        printf("%d ",h->data[i]);
    }
    printf("\n");
}

/*堆排序*/
void heap_sort(int a[],int n) {
    int i;
    heap *h=(heap*)malloc(sizeof(heap));/*给堆指针分配空间*/
    init(h);/*初始化堆*/
    for(i=0; i<n; i++) {/*将数组的元素依次插入堆*/
        insert(h,a[i]);
    }
    for(i=0; i<n; i++) {
        a[i]=deleteMin(h);
    }
}
/*遍历数组*/
void travel_array(int a[],int n) {
    int i;
    for(i=0; i<n; i++) {
        printf("%d ",a[i]);
    }
    printf("\n");
}

main() {
    int a[]= {67,8,4,34,86,87,6,45,7,864,56,1,3,78,9,13};
    int n=sizeof(a)/sizeof(int);
    travel_array(a,n);
    heap_sort(a,n);
    travel_array(a,n);
}

 

posted @ 2018-09-07 11:14  Mars.wang  阅读(1697)  评论(0编辑  收藏  举报