算法导论 第十九章 斐波那契堆

ps:这章写的挺烂的,感觉没头没尾的提出一个结构和算法,然后说明它具有这些性质。



19.1 斐波那契堆结构

def:一个斐波那契堆是一系列最有最小堆的有根树集合。也就是说每棵树均遵循最小堆性质:每个节点的关键字大于或等于它的父节点的关键字,节点结构定义如下:

class NODE():
    def __init__(self, key):
        self.key = key
        self.left = self
        self.right = self
        self.parent = None
        self.child = None
        self.degree = 0
        self.mark = False

class FIB_HEAP():
    def __init__(self):
        self.num = 0
        self.min = None
        self.rootList = None
我们使用摊还分析的势函数分析方法来分析其复杂度:

我们可以实现如下的算法来保证上表中的复杂度能够成立:

import math

class NODE():
    def __init__(self, key):
        self.key = key
        self.left = self
        self.right = self
        self.parent = None
        self.child = None
        self.degree = 0
        self.mark = False

class FIB_HEAP():
    def __init__(self):
        self.num = 0
        self.min = None
        self.rootList = None

class DL_LIST():
    def __init__(self):
        self.nil = NODE(None)
        self.nil.right = self.nil
        self.nil.left = self.nil
        

def DL_LIST_SEARCH(L, k):
    x = L.nil.right
    while x != L.nil and x.key != k:
        x = x.right
    return x

def DL_LIST_INSERT(L, x):
    x.right = L.nil.right
    L.nil.right.left = x
    L.nil.right = x
    x.left = L.nil

def DL_LIST_INSERT_BEFORE(L, x, y):
    y.left = x.left
    y.right = x
    x.left.right = y
    x.left = y
    

def DL_LIST_DELETE(L, x):
    x.left.right = x.right
    x.right.left = x.left

def DL_LIST_UNION(L1, L2):
    head1 = L1.nil.right
    tail1 = L1.nil.left

    head2 = L2.nil.right
    tail2 = L2.nil.left

    tail1.right = head2
    head2.left = tail1
    tail2.right = L1.nil
    L1.nil.left = tail2

    L2.nil.left = None
    L2.nil.right = None
    

def DL_LIST_PRINT(L):
    y = L.nil.right
    while y != L.nil:
        print(y.key, y.mark, y.degree)
        if y.child != None:
            print("---------child of ", y.key)
            DL_LIST_PRINT(y.child)
            print("----------child end")
        y = y.right


def FIB_HEAP_INSERT(H, x):
    x.parent = None
    x.child = None
    x.degree = 0
    x.mark = False
    if H.min == None:
        H.root = DL_LIST()
        DL_LIST_INSERT(H.root, x)
        H.min = x
    else:
        DL_LIST_INSERT_BEFORE(H.root, H.min, x)
        if x.key < H.min.key:
            H.min = x
    H.num = H.num + 1

def FIB_HEAP_UNION(H1, H2):
    H = FIB_HEAP()
    H.min = H1.min
    DL_LIST_UNION(H.root, H2.root)
    if (H1.min == None) or (H2.min != None and H2.min.key < H1.min.key):
        H.min = H2.min
    H.num = H1.num + H2.num
    
    H1.root = None
    H1.min = None
    H2.root = None
    H2.min = None

    return H

def FIB_HEAP_EXTRACT_MIN(H):
    z = H.min
    if z != None:
        if z.child != None:
            x = z.child.nil.right
            while x != z.child.nil:
                x.parent = None
                y = x.right
                DL_LIST_INSERT_BEFORE(H.root, H.min, x)
                x = y
        
        DL_LIST_DELETE(H.root, z)

        if H.root.nil.right == H.root.nil  and H.root.nil.left == H.root.nil:
            H.min = None
        else:
            H.min = z.right
            CONSOLIDATE(H)
        H.num = H.num -1
    return z

def D(num):
    return int(math.log(num, 2))+1

def CONSOLIDATE(H):
    A = [None for i in range(D(H.num)+1)]
    w = H.min
    last = w.left
    flag = True
    while flag:
        x = w
        w = w.right
        if x == H.root.nil:
            continue
        elif x == last:
            flag = False
        d = x.degree
        while A[d] != None:
            y = A[d]
            if x.key > y.key:
                temp = x
                x = y
                y = temp
            FIB_HEAP_LINK(H, y, x)
            A[d] = None
            d = d + 1
        A[d] = x

    H.min = None
    for i in range(0, D(H.num)+1):
        if A[i] != None:
            if H.min == None:
                H.root = DL_LIST()
                DL_LIST_INSERT(H.root, A[i])
                H.min = A[i]
            else:
                DL_LIST_INSERT_BEFORE(H.root, H.min, A[i])
                if A[i].key < H.min.key:
                    H.min = A[i]
            

def FIB_HEAP_LINK(H, y, x):
    DL_LIST_DELETE(H.root, y)
    if x.child == None:
        x.child = DL_LIST()
    DL_LIST_INSERT(x.child, y)
    x.degree = x.degree + 1
    y.parent = x
    y.mark = False

def FIB_HEAP_DECREASE_KEY(H, x, k):
    if k > x.key:
        raise("new key is greater than current key")

    x.key = k
    y = x.parent
    if y != None and x.key < y.key:
        CUT(H, x, y)
        CASCADING_CUT(H, y)
    if x.key < H.min.key:
        H.min = x

def CUT(H, x, y):
    DL_LIST_DELETE(y.child, x)
    y.degree = y.degree - 1
    DL_LIST_INSERT_BEFORE(H.root, H.min, x)
    x.parent = None
    x.mark = False

def CASCADING_CUT(H, y):
    z = y.parent
    if z != None:
        if y.mark == False:
            y.mark = True
        else:
            CUT(H, y, z)
            CASCADING_CUT(H, z)

def FIB_HEAP_DELETE(H, x):
    FIB_HEAP_DECREASE_KEY(H, x, -float("inf"))
    FIB_HEAP_EXTRACT_MIN(H)

if __name__ == "__main__":
    H = FIB_HEAP()
    node24 = NODE(24)
    FIB_HEAP_INSERT(H, node24)
    node17 = NODE(17)
    FIB_HEAP_INSERT(H, node17)
    node3 = NODE(3)
    FIB_HEAP_INSERT(H, node3)
    node23 = NODE(23)
    FIB_HEAP_INSERT(H, node23)    
    node7 = NODE(7)
    FIB_HEAP_INSERT(H, node7)
    
    node39 = NODE(39)
    FIB_HEAP_INSERT(H, node39)    
    node18 = NODE(18)
    FIB_HEAP_INSERT(H, node18)
    node52 = NODE(52)
    FIB_HEAP_INSERT(H, node52)    
    node38 = NODE(38)
    FIB_HEAP_INSERT(H, node38)    
    node41 = NODE(41)
    FIB_HEAP_INSERT(H, node41)    
    node30 = NODE(30)
    FIB_HEAP_INSERT(H, node30)    
    node35 = NODE(35)
    FIB_HEAP_INSERT(H, node35)    
    node26 = NODE(26)
    FIB_HEAP_INSERT(H, node26)    
        
    node46 = NODE(46)
    FIB_HEAP_INSERT(H, node46)

    FIB_HEAP_LINK(H, node39, node18)
    FIB_HEAP_LINK(H, node41, node38)
    FIB_HEAP_LINK(H, node35, node26)
    node39.mark = True

    
    FIB_HEAP_LINK(H, node38, node3)
    FIB_HEAP_LINK(H, node52, node3)
    FIB_HEAP_LINK(H, node18, node3)
    FIB_HEAP_LINK(H, node30, node17)
    FIB_HEAP_LINK(H, node46, node24)
    FIB_HEAP_LINK(H, node26, node24)
    node18.mark = True
    node26.mark = True

    print("init ********************")
    DL_LIST_PRINT(H.root)

    print("insert ******************")
    node21 = NODE(21)
    FIB_HEAP_INSERT(H, node21)
    DL_LIST_PRINT(H.root)

    print("extract******************")
    FIB_HEAP_EXTRACT_MIN(H)
    DL_LIST_PRINT(H.root)

    print("decrease*****************")
    FIB_HEAP_DECREASE_KEY(H, node46, 15)
    DL_LIST_PRINT(H.root)
    print("decrease-----------------")
    FIB_HEAP_DECREASE_KEY(H, node35, 5)
    DL_LIST_PRINT(H.root)

    print("delete*******************")
    FIB_HEAP_DELETE(H, node18)
    DL_LIST_PRINT(H.root)


19.4 最大度数的界


习题解答



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值