数据结构——第五讲、树(下)(1)

5.1 堆

当需要存储一个不同优先级的优先队列时(删除都删除最大/最小值,插入任意元素),我们就要用到堆,当然,用数组,链表,或树都可以完成,但是算法复杂度不够理想。

堆是一种特殊的树,它的任意节点都比它的左右儿子大/小,所以它的根节点是最大的/或者是最小的,删除的时候只需要删除最上面的根节点即可,插入时,为了使空间利用率最大,按照完全二叉树插入,这就是最大/小堆

还记得刚开始说二叉树的时候,我们试过用数组存储二叉树,然而因为利用率不高,只适合存完全二叉树这种排的比较满的树,对于现在堆这种结构,我们就可以用数组来存,从上到下一层一层排序,第i个节点左儿子是2*i,右儿子是2*i+1,父节点是i/2。

堆的抽象数据类型描述:
类型名称:最大堆(MaxHeap)
数据对象集:完全二叉树
操作集:

MaxHeap Create(int MaxSize);
Boolean IsFull(MaxHeap H);
Boolean IsEmpty(MaxHeap H);
MaxHeap Insert(ElementType x, MaxHeap H);
ElementType Delete(MaxHeap H);

最大堆的结构

typedef struct HeapStruct *MaxStruct;
struct HeapStruct{
    //指向数组
    ElementType *Elements;
    //现有元素个数
    int Size;
    //最大容量
    int Capacity;
};

创建一个最大堆

MaxHeap Create(int MaxSize){
    MaxHeap H = malloc(sizeof(struct HeapStruct));
    //数组空出一个位置存放最大值作为哨兵
    H->Elements = malloc(sizeof((MaxSize+1)*ElementType));
    H->Size = 0;
    H->Capacity = MaxSize;
    //宏定义一个数据里面的最大可能值,插入时可以减少一个判断条件。
    H->Elements[0] = MaxData;
    return H;
}

插入

MaxHeap Insert(ElementType x, MaxHeap H){
    int i;
    if(IsFull(H)){
        printf("已满!");
        return NULL;
    }
    //改变最大堆信息的同时,告诉i应该插入的位置
    i = ++H->Size;
    for(;H->Elements[i/2] < x;i /= 2){
        H->Elements[i] = H->Elements[i/2];
    }
    H->Elements[i] = x;
    return H;
}

删除

ElementType Delete(MaxHeap H){
    if( IsEmpty(H) ){
        printf("堆空!");
        return NULL;
    }
    ElementType MaxItem = H->Elements[1];
    ElementType item;
    int parent = 1;
    int child;
    item = H->Elements[H->Size--];
    for(;2*parent <= H->Size;parent = child){
        child = 2 * parent;
        if( child != H->Size){
            if( H->Elements[child] < H->Elements[child+1])
                child++;
        }
        if(item >= H->Elements[child])break;
        else
            H->Elements[parent] = H->Elements[child];
    }
    H->Elements[parent] = item;
    return MaxItem;
}

给定一个序列,创建一个堆,可以通过不断的插入,但是有效率更高的方法,先把序列存入完全二叉树中,然后从最后一个有儿子的节点开始调整,形成一个节点,他的左右儿子都是堆的递归

//这段代码未经验证,有什么问题希望能反馈给我……
MaxHeap Create(ElementType T[Size]){
    MaxHeap H;
    for(int i = 0; i < Size; i++)
        H->Elements[++H->Size] = T[i];

    int parent = H->Size/2;
    int child;
    ElementType t;
    for(;parent>0;parent--){
        for(;2*parent <= H->Size;parent = child){
            child = 2 * parent;
            if( child != H->Size){
                if( H->Elements[child] < H->Elements[child+1])
                    child++;
            }
            if(H->Elements[parent] >= H->Elements[child])break;
            else{
                t = H->Elements[parent];
                H->Elements[parent] = H->Elements[child];
                H->Elements[child] = t;
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/github_39312212/article/details/78164509