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 @   Mars.wang  阅读(1743)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示