堆
堆是一种图的树形结构,被用来实现“优先队列”(priority queues)。优先队列是一种数据结构,可以自由添加数据,但是取出的数据时要从最小值开始按顺序取出。在堆的树形结构中,各个顶点称为“node”结点,数据就存储在这些结点中。
结点内的数据就是存储的数据,堆中每个结点有2个子结点。树的形状取决于数据的个数,另外,结点的排列顺序为从上到小,同一行里则为从左到右。
1、添加数据。在堆中存储数据时必须遵守这样一个规则:子结点必定大于父结点。因此,最小值被存储在顶端的根结点中。往堆中添加数据时,为了遵守这条规则,一般会把新数据放最下面一行靠左的位置。当最下面一行没有多余空间时,就再往下另起一行,把数据加在这一行的最左端。
比如添加数字5,首先寻找新数据的位置,该图最下面空着一个位置,所以把数据放在此处。
如果父结点大于子结点,则不符合规则,需要交换父子结点的位置。
因为父结点6比子结点5大,所以进行交换。重复这样的操作,直到数据都符合规则,不再需要交换为止。
2、取出数据。从堆中取数据的时候,取出的是最上面的数据,这样堆中就能保持最上面的数据最小。
因为最上面的数据被取出了,所以堆的结构就需要调整了。
将最后的数据放到最顶端
如果子结点的数字小于父结点的,就将父结点与其左右两个子结点中较小的一个进行交换。
因为父结点6比子结点5、3大,所以将父节点与子结点进行位置交换,父结点的左结点3比右结点5小,因此将父结点6与左结点3进行交换重复此操作,直到所有数据都符合规则,不再需要进行交换为止。
现在子结点8大于父结点的6,大于左子结点4,需要将左边的子结点与父结点进行交换。
从堆中取数据就完成了。
备注:
- 堆中最顶端的数据始终最小,所以无论多少数据量,取出最小值的时间复杂度都是O(1)。
- 因为取出的数据后需要将最后的数据移动到最顶端,然后一边比较它与子结点数据的大小,一边往下移动,所以取出数据需要的运行时间和树的高度成正比。假设数据量为n,根据堆的形状特点,可知数的高度是log2n,那么重构是的时间复杂度是O(logn)。
- 添加数据后,数据会在一边比较它与父结点数据的大小,一边往上移动,直到满足堆的条件为止,所以添加数据需要的运行时间与树的高度成正比,也是O(logn)。
欢迎批评指正,提出问题,谢谢!