浅谈数据结构——堆

来源:互联网 发布:阿铭linux第二版 编辑:程序博客网 时间:2024/06/02 19:55

今天来跟大家说说堆,他是一种树形数据结构。

        堆(heap)是一种神奇的东西,他每次替换,查找只需要nlogn的时间复杂度。看到这个,当然想到了是用数组来存。

堆就像是一棵树。例如

         (1)

        /    \

     (2)    (3)

    /  \   /  \

  (4)  (5)  (6)  (7)

括号里代表的是他的序号,然后存的时候就是heap[k]就可以了。

父亲节点和他的左儿子,右儿子序号的关系是:

假设父亲节点为k

那么左儿子为2K,右儿子为2K+1,大家可以试试。

堆有小根堆和大根堆

小根堆就是一个父亲节点比两个儿子小,当然堆顶就是最小元素了,反之就是大根堆

         (1)

        /    \

     (2)    (3)

    /  \      /  \

  (20) (5) (6)  (7)

例如这个就是小根堆。小根堆的作用很大。


小根堆的维护:

有2种维护,一种是替换堆顶,另一种是加入元素

1、替换堆顶
替换堆顶,可能就会违背了小根堆堆顶最小的。。(想不出一个词汇,望大神指导)。所以我们就要把堆顶替换。例如替换成如下

         (10)

        /    \

     (2)    (3)

    /  \      /  \

  (20) (5) (6)  (7)

然后一开始,他的左儿子和右儿子都是比他小的,也就是说都可以替换,如果遇到这样的情况,则替换最小的那个,换明显换掉2.

         (2)

        /    \

    (10)    (3)

    /  \      /  \

  (20) (5) (6)  (7)

然后变成这个样子,这时候还是不符合,因为还是有一个儿子比他小,所以我们就替换比他小的儿子,把5替换掉,这里就不贴图了。用代码来实现就是:

procedure heapdown(x:Longint);var        t:longint;begin        t:=x;        if (x*2<=k)and(heap[x*2]<heap[t]) then t:=x*2;//这个就是判断一下下面有没有比他小的        if (x*2+1<=k)and(heap[x*2+1]<heap[t]) then t:=x*2+1;如果有的话,就把t赋值为最小那个,是一个技巧        if t<>x then//如果存在最小        begin                swap(heap[x],heap[t]);//则替换                heapdown(t);//递归寻找,方便简洁        end;end;


2:插入
例如

         (1)

        /    \

    (2)    (3)

    /  \      /  \

  (4) (5) (6) 

插入了一个3

         (1)

        /    \

    (2)    (3)

    /  \      /  \

  (4) (5) (6) (2)

然后现在就不符合条件了。可知一个节点它的的父亲节点一定是它的位置div 2,自己想想。

然后现在2他比爸爸还要小,跟爸爸换位置,然后就符合小根堆的条件了

         (1)

        /    \

    (2)    (2)

    /  \      /  \

  (4) (5) (6) (3)

实现也是用递归

procedure heapup(x:longint);begin        if (x shr 1>0) and (heap[x shr 1]>heap[x]) then//如果当前不为这个堆的堆顶,且可替换        begin                swap(heap[x],heap[x shr 1]);//替换                heapup(x shr 1);//递归        end;end;
这是我自学的内容,如果有错误,或者有需要的地方可以再评论联系我,欢迎指出及批评。


1 0