数据结构-堆 的基本操作

目录

堆的结构体

堆的创建

堆的插入操作

堆的调整

堆的删除操作

堆排序

完整代码


堆的结构体

struct Heap {
    int *data;   //数组首地址
    int length;   //堆中元素的数量
    int maxsize;   //堆中的最大容量
};

堆的创建

struct Heap * initialize(int maxsize){   //初始化堆
    struct Heap * mHeap;
    mHeap = (struct Heap *)malloc(sizeof(struct Heap));
    mHeap->data = (int *)malloc((maxsize+1) * sizeof(int));
    mHeap->length = 0;
    mHeap->maxsize = maxsize;
    mHeap->data[0] = 945034985;   //创建哨兵
    return mHeap;
}

堆的插入操作

//插入堆
void insert(struct Heap *mHeap,int x){
    if(mHeap->length == mHeap->maxsize){
        printf("堆已满!");
        return;
    }
    int i = ++mHeap->length;
    mHeap->data[i] = x;  //插入最后的位置
    while(x > mHeap->data[i/2]) {
        mHeap->data[i] = mHeap->data[i / 2];
        i = i / 2;  //指向下标变为修改后父节点位置;继续判断(往上走)
    }
    mHeap->data[i] = x;
}

堆的调整

void percDown(struct Heap *mHeap,int i){   //调整已有中的位置
    int w = mHeap->data[i];
    int k = i*2;  //儿子结点  i为父亲下标
    for(;k <= mHeap->length; k = i * 2) {
        if (k < mHeap->maxsize && mHeap->data[k] < mHeap->data[k + 1]) {
            k++;
        }
        if(w >= mHeap->data[k]) break;
        else {
            mHeap->data[i] = mHeap->data[k];  //进行交换
            i = k;
        }
    }
    mHeap->data[i] = w;
}

void BuildMaxHeap(struct Heap *mHeap){
    int i;
    for(i = mHeap->length/2;i>0;i--){   //只需要调整非终端结点即可
        percDown(mHeap,i);
    }
}

堆的删除操作

void delete(struct Heap *mHeap,int x){
    int i;
    for( i = 1;i<= mHeap->length;i++){  //查找需要删除的数组下标
        if(mHeap->data[i] == x){
            break;
        }
    }
    mHeap->data[i] = mHeap->data[mHeap->length];  //最后一个代替他
    mHeap->length--;
    BuildMaxHeap(mHeap);  //调整
}

堆排序

void sortHeap(struct Heap *mHeap){

    if(mHeap == NULL){
        return;
    }
    int length = mHeap->length;
    while(length >= 1){
        int w = mHeap->data[1];   //当前为堆中的最大值
        //将最大值与最后一位调换
        mHeap->data[1] = mHeap->data[length];
        mHeap->data[length] = w;
        length--;  //最后一位不用在参与下面的调整

        for(int i = length/2;i >= 1;i--){  //只需要调整非终端结点即可
            int child = 2 * i;
            int cnt = i;  //被检查的父亲结点数组下标
            int D = mHeap->data[cnt];   //被调整结点的数据
            for(;child <= length;child = cnt * 2) {
                if (child < length && mHeap->data[child] < mHeap->data[child + 1]) {
                    child++;
                }
                if (mHeap->data[child] <= D) {
                    break;
                }else{
                    mHeap->data[cnt] =  mHeap->data[child];
                    cnt = child;
                }
            }
            mHeap->data[cnt] = D;
        }
    }
}

完整代码

#include <stdio.h>
#include <stdlib.h>

struct Heap {
    int *data;   //数组首地址
    int length;   //堆中元素的数量
    int maxsize;   //堆中的最大容量
};

struct Heap * initialize(int maxsize){   //初始化堆
    struct Heap * mHeap;
    mHeap = (struct Heap *)malloc(sizeof(struct Heap));
    mHeap->data = (int *)malloc((maxsize+1) * sizeof(int));
    mHeap->length = 0;
    mHeap->maxsize = maxsize;
    mHeap->data[0] = 945034985;   //创建哨兵
    return mHeap;
}

void percDown(struct Heap *mHeap,int i){   //调整已有中的位置
    int w = mHeap->data[i];
    int k = i*2;  //儿子结点  i为父亲下标
    for(;k <= mHeap->length; k = i * 2) {
        if (k < mHeap->maxsize && mHeap->data[k] < mHeap->data[k + 1]) {
            k++;
        }
        if(w >= mHeap->data[k]) break;
        else {
            mHeap->data[i] = mHeap->data[k];  //进行交换
            i = k;
        }
    }
    mHeap->data[i] = w;
}

void BuildMaxHeap(struct Heap *mHeap){
    int i;
    for(i = mHeap->length/2;i>0;i--){   //只需要调整非终端结点即可
        percDown(mHeap,i);
    }
}

//插入堆
void insert(struct Heap *mHeap,int x){
    if(mHeap->length == mHeap->maxsize){
        printf("堆已满!");
        return;
    }
    int i = ++mHeap->length;
    mHeap->data[i] = x;  //插入最后的位置
    while(x > mHeap->data[i/2]) {
        mHeap->data[i] = mHeap->data[i / 2];
        i = i / 2;  //指向下标变为修改后父节点位置;继续判断(往上走)
    }
    mHeap->data[i] = x;
}


//堆的输出
void printHeap(struct Heap *mHeap){
    for(int i = 1;i<= mHeap->length;i++){
        printf("%d ",mHeap->data[i]);
    }
}

void delete(struct Heap *mHeap,int x){
    int i;
    for( i = 1;i<= mHeap->length;i++){  //查找需要删除的数组下标
        if(mHeap->data[i] == x){
            break;
        }
    }
    mHeap->data[i] = mHeap->data[mHeap->length];  //最后一个代替他
    mHeap->length--;
    BuildMaxHeap(mHeap);  //调整
}

//堆排序
void sortHeap(struct Heap *mHeap){

    if(mHeap == NULL){
        return;
    }
    int length = mHeap->length;
    while(length >= 1){
        int w = mHeap->data[1];   //当前为堆中的最大值
        //将最大值与最后一位调换
        mHeap->data[1] = mHeap->data[length];
        mHeap->data[length] = w;
        length--;  //最后一位不用在参与下面的调整

        for(int i = length/2;i >= 1;i--){  //只需要调整非终端结点即可
            int child = 2 * i;
            int cnt = i;  //被检查的父亲结点数组下标
            int D = mHeap->data[cnt];   //被调整结点的数据
            for(;child <= length;child = cnt * 2) {
                if (child < length && mHeap->data[child] < mHeap->data[child + 1]) {
                    child++;
                }
                if (mHeap->data[child] <= D) {
                    break;
                }else{
                    mHeap->data[cnt] =  mHeap->data[child];
                    cnt = child;
                }
            }
            mHeap->data[cnt] = D;
        }
    }
}


int main(){
    int maxsize;
    int x,i,c;
    printf("数组的最大长度:");
    scanf("%d",&maxsize);
    struct Heap *mHeap = initialize(maxsize);   //初始化
    scanf("%d",&x);
    while(x != -1){
        mHeap->data[++mHeap->length] = x;
        scanf("%d",&x);
    }
    BuildMaxHeap(mHeap);
    printf("堆调整后:");
    printHeap(mHeap);

    printf("\n请输入你要插入的数据:");
    scanf("%d",&i);
    insert(mHeap,i);
    BuildMaxHeap(mHeap);
    printf("插入后:");
    printHeap(mHeap);
    //printf("%d",mHeap->length);
    printf("\n输入需要删除的数据:");
    scanf("%d",&c);
    delete(mHeap,c);
    printf("删除后:");
    printHeap(mHeap);
    sortHeap(mHeap);
    printf("\n堆排序:");
    printHeap(mHeap);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值