堆的插入与删除

在上一篇博客中,我详细探讨了堆的创建与调整,这一篇基于上一篇(https://blog.csdn.net/xinger_28/article/details/82926744)的基础上讨论堆的插入与删除。

首先声明此堆为小堆。小堆与大堆代码相似,原理相似

小堆的插入:在已经建成的最小堆的后面插入要插入的新元素,插入之后,当节点不满足小堆的性质时,对对重新进行向下调整。

(关于为何用新元素插入最后,就我个人而言,是为了减少调整次数,毕竟若新元素放在后面恰巧满足堆的性质就不需要调整,总体而言,调整次数减少;若将新元素放在最前面或者任一位置,有非常大的概率破坏堆的完整性,可能需要对堆进行一次新的建立,个人观点,不喜勿喷。)

 

小堆的删除:删除时每次删除堆顶元素。

删除方法:

1)判断需要删除的元素所在位置是否存在,若不存在,结束;若存在,位置为K,则下一步。

2)将堆的最后一个元素代替要删除的元素,将堆的元素个数减少一个。

3)重新对堆进行调整,直到满足堆的性质。

代码如下:

头文件:二叉堆.h

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

#define Max 100

typedef int DataType;
//typedef int size_t;

//二叉堆
typedef struct StackN
{
    DataType array[Max];
    //size_t size;
    int size;
}StackN;

void init(StackN * php)
{
    php->size = 0;
    php = NULL;
}

//让数据入堆
void CreatS(DataType a[], StackN*php, int n)
{
    if (n == 0)
    {
        return;
        printf("内容为空!\n");
    }
    int i = 0;
    for (i = 0; i < n; i++)
    {
        php->array[i] = a[i];
        php->size++;
    }
}

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


void AdJust(StackN*php,  int root)
{
    while (1) {
        int left = 2 * root + 1;
        int right = 2 * root + 2;
        // 判断是否是叶子结点,如果左孩子下标越界了,没有左孩子了
        // 所以也就没有右孩子了
        if (left > php->size) {    // == 的情况也是越界
            // 越界
            return;
        }

        int min = left;    // 假设大的那个是左孩子
        // 找到左右孩子中大的一个
        // 一定要先判断右孩子有,才能比较左右孩子的大小
        // if (array[right] > array[left] && right < size),错误的
        if (right <= php->size && php->array[right] < php->array[left]) {
            min = right;
        }

        // 判断和 [root] 的关系
        // root >= max    错误的, root 和 max 表示的下标
        if (php->array[root] <= php->array[min]) {
            return;
        }

        // 交换
        int t = php->array[root];
        php->array[root] = php->array[min];
        php->array[min] = t;

        root = min;
    }
}


void A_S(StackN*php)
{
    int i = 0;
    for (i = (php->size/2-1); i >= 0; i--)
        AdJust(php, i);
    printf("\n");
}


//堆的插入
void Insert(StackN*php, DataType data)
{
    php->array[php->size] = data;
    php->size++;
    int i = 0;
    for (i = (php->size-1) / 2 - 1; i >= 0; i--)
        AdJust(php, i);
    printf("\n");
}

//堆的删除
void Pop(StackN*php, DataType data)
{
    int i = 0;
    for (i = 0; i <php->size; i++)
    {
        if (data == php->array[i])
        {
            break;
        }
    }
    if (i == php->size)
    {
        printf("堆中没有此元素\n");
        return;
    }
    php->array[i] = php->array[php->size-1];
    php->size--;
    A_S(php);
    printf("\n");
}

//打印堆
void Print(StackN*php)
{
    int i = 0;
    for (i = 0; i < php->size; i++)
        printf("%d ", php->array[i]);
    printf("\n");
}
void test()
{
    StackN php;
    init(&php);
    DataType aa[] = { 53, 17, 78, 9, 45, 65, 87, 23, 31 };  //堆   调整为小堆
    int n = sizeof(aa) / sizeof(DataType);
    CreatS(aa, &php, n);
    Print(&php);

    A_S(&php);
    Print(&php);

    Insert(&php, 110);
    Print(&php);
    printf("加入成功\n");

    Pop(&php, 78);
    Print(&php);

    printf("\n  >");
    Pop(&php, 55);
    Print(&php);
}

源文件: test.cpp

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值