python算法复习(六)----有序表(详解 AVL树和跳表 )和并查集

# 本章的内容是有序表和并查集,
# 在学习哈希表的时候我们提到过哈希表的构成可以使用单链表,那么我们能不能使用更高效、更多功能的方式完成呢
# 在图的最小生成树的kruskal算法中就简单接触到了并查集的简单功能,这次会完整的实现整个结构


# 岛问题(引出并查集结构)
# 一个矩阵中只有0和1两种值,每个位置都可以和自己的上下左右四个位置相连,如果有一片1连在一起,这个部分叫做一个岛,求一个矩阵中有多少个岛
# 解题思路:从左上开始遍历整个矩阵,当遇到1的时候,看看它的上下左右是不是也是1,如果是1就把他变成2。这样后续遍历就不会把这些识别为岛
import random


def howManyisland(map):
    if map == [] or map[0] == []:
        return 0
    res = 0
    for i in range(len(map)):
        for j in range(len(map[0])):
            if map[i][j] == 1:
                res += 1
                island(map, i, j)
    return res


def island(map, i, j):
    if i < 0 or j < 0 or i >= len(map) or j >= len(map[0]) or map[i][j] != 1:
        return
    map[i][j] = 2
    island(map, i + 1, j)
    island(map, i - 1, j)
    island(map, i, j + 1)
    island(map, i, j - 1)


# 思考一下,如何设计一个并行算法解决岛问题(多线程分片处理一个大map,如何合并不同线程的答案?)
# 在这之前我们先学习并查集结构
# 并查集
# 并查集的两个重要的方法:1.查询两个集合是否相同,2.合并两个集合
# 并查集的时间复杂度:当findHeadNode()方法被调用O(N)级别以上后,可以认为findHeadNode()为O(1)
class UnionFind_Node(object):
    def __init__(self, value):
        self.value = value

    def __repr__(self):
        return str(self.value)


class UnionFind_set(object):
    def __init__(self, arr):
        self.nodemap = dict()
        self.fatermap = dict()
        self.lenghtmap = dict()
        for value in arr:
            node = UnionFind_Node(value)
            self.nodemap[value] = node  # value对应的UnionFind_Node结构
            self.fatermap[node] = node  # UnionFind_Node的fatherNode
            self.lenghtmap[node] = 1  # UnionFind_Node为头的长度

    def findHeadNode(self, node):
        # 查找node的头节点,在查找头节点的过程中,把沿路的节点保存好。
        # 返回时把沿路节点的父节点都设置为头节点,扁平化路径
        buffer = []
        while node != self.fatermap[node]:
            buffer.append(node)
            node = self.fatermap[node]
        while buffer != []:
            self.fatermap[buffer.pop()] = node
        return node

    def isSameSet(self, value_A, value_B):
        # 查询两个的头节点是否为同一个节点
        if value_A in self.nodemap and value_B in self.nodemap:
            node_A = self.nodemap[value_A]
            node_B = self.nodemap[value_B]
            A_father = self.findHeadNode(node_A)
            B_father = self.findHeadNode(node_B)
            return A_father == B_father
        return False

    def union(self, value_A, value_B):
        # 把较小的那个集合合并较大的集合里(把较小的那个的头节点的父节点设置为较大的集合的头节点,再删去记录)
        if value_A in self.nodemap and value_B in self.nodemap:
            if self.isSameSet(value_A, value_B) == False:
                A_father = self.findHeadNode(self.nodemap[value_A])
                B_father = self.findHeadNode(self.nodemap[value_B])
                if self.lenghtmap[A_father] >= self.lenghtmap[B_father]:
                    self.fatermap[B_father] = A_father
                    self.lenghtmap[A_father] += self.lenghtmap[B_father]
                    self.lenghtmap.pop(B_father)
                else:
                    self.fatermap[A_father] = B_father
                    self.lenghtmap[B_father] += self.lenghtmap[A_father]
                    self.lenghtmap.pop(A_father)

    def __repr__(self):
        return str(self.lenghtmap)


# 现在再来看看如何并行的解决岛问题
# 首先,我们要知道,如果单纯的相加是可能会导致岛的数量变多的(如下图所示)
# [1,1,1,1,1,1,1,1]     [1,1,1,1] [1,1,1,1]
# [1,0,0,0,0,0,0,1]     [1,0,0,0] [0,0,0,1]
# [1,0,1,1,1,1,1,1]     [1,0,1,1] [1,1,1,1]
# [1,0,1,0,0,0,0,0]---> [1,0,1,0] [0,0,0,0]
# [1,0,1,1,1,1,1,1]     [1,0,1,1] [1,1,1,1]
# [1,0,0,0,0,0,0,1]     [1,0,0,0] [0,0,0,1]
# [1,1,1,1,1,1,1,1]     [1,1,1,1] [1,1,1,1]
# 现在我们在切分边界上标记出岛A、B、C、D
# [1,1,1,1,1,1,1,1]     [1,1,1,1] [1,1,1,1]     [1,1,1,A] [C,1,1,1]
# [1,0,0,0,0,0,0,1]     [1,0,0,0] [0,0,0,1]     [1,0,0,0] [0,0,0,1]
# [1,0,1,1,1,1,1,1]     [1,0,1,1] [1,1,1,1]     [1,0,1,B] [C,1,1,1]
# [1,0,1,0,0,0,0,0]---> [1,0,1,0] [0,0,0,0]---> [1,0,1,0] [0,0,0,0]
# [1,0,1,1,1,1,1,1]     [1,0,1,1] [1,1,1,1]     [1,0,1,B] [D,1,1,1]
# [1,0,0,0,0,0,0,1]     [1,0,0,0] [0,0,0,1]     [1,0,0,0] [0,0,0,1]
# [1,1,1,1,1,1,1,1]     [1,1,1,1] [1,1,1,1]     [1,1,1,A] [D,1,1,1]
# 得到A、B、C、D四个集合,检查相连出A、C是否为同一个集合,不是则合并(A、C)岛的数量4-1。
# 检查相连(A、C)和B是否为同一个集合,不是则合并(A、B、C)岛的数量4-1-1。
# 检查相连的(A、B、C)和D是否为同一个集合,不是则合并(A、B、C、D)岛的数量4-1-1-1。
# 检查相连的(A、B、C、D)和D是否为同一个集合,是则不做任何操作
# 所以岛的数量为4-1-1-1=1
# 花费的时间从遍历一整个大map,变成了遍历一半map加上查看边界的时间


'''
    下面是有序表的内容,包括红黑树、AVL、SB树、跳表四中结构。
    什么是有序表?O(logN)
        有序表除了支持哈希表的所有操作之外,还支持按照key有序组织(哈希表是繁乱组织的)
        可以找到最小的key,找到最大的key,以及找到大于等于某value的最近的key
    其中红黑树、AVL、SB树都是平衡搜索二叉树。
'''


# 搜索二叉树:左树 < 头 < 右树
# 搜索二叉树的删除:
#     一、如果是根节点:
#         1.没有左右孩子,直接把根节点指向空
#         2.只有一个子树,
#               ① 左孩子cur无右树 (右孩子无左树),把根节点指向cur
#               ② 左孩子有右树 (右孩子有左树),找到左孩子最右的节点 (右孩子最左的节点)cur2和它的父节点p2。
#                  把cur2的左树(右树)接到p2的右树(左树),把根节点的左孩子(右孩子)接到cur2的左树(右树),根节点指向cur2
#         3.左右孩子双全,
#               ① 左孩子cur无右树,把根节点的右孩子接到cur右树,把根节点指向这个节点
#               ② 左孩子有右树,找到左孩子最右的节点,cur2和它的父节点p2。
#                  把cur2的左树接到p2的右树,把根节点的左孩子接到cur2的左树,根节点的右孩子接到cur2的右树,根节点指向cur2
#     二、不是根节点:
#         不断向下找找到要删除的cur和他的父节点p (把原来指向根节点的,改成cur对应p的方向)
#         1.没有左右孩子,直接把p对应的方向指向空
#         2.只有一个子树,
#               ① 左孩子cur2无右树 (右孩子无左树),把p对应的方向指向cur2
#               ② 左孩子有右树 (右孩子有左树),找到左孩子最右的节点 (右孩子最左的节点)cur2和它的父节点p2。
#                  把cur2的左树(右树)接到p2的右树(左树),把cur的左孩子(右孩子)接到cur2的左树(右树),p对应的方向指向cur2
#         3.左右孩子双全,
#               ① 左孩子cur2无右树,把cur的右孩子接到cur2右树,把p对应的方向指向这个节点
#               ② 左孩子有右树,找到左孩子最右的节点,cur2和它的父节点p2。
#                  把cur2的左树接到p2的右树,把cur的左孩子接到cur2的左树,cur的右孩子接到cur2的右树,p对应的方向指向cur2
class TreeNode(object):
    def __init__(self, value):
        self.value = value
        self.left = None
        self.right = None

    def __repr__(self):
        return str(self.value)


class BST(object):

    def __init__(self):
        self.root = None

    def add(self, value):
        node = TreeNode(value)
        if self.root == None:
            self.root = node
            return
        cur = self.root
        while True:
            if node.value < cur.value:
                if cur.left == None:
                    cur.left = node
                    return
                cur = cur.left
            elif node.value > cur.value:
                if cur.right == None:
                    cur.right = node
                    return
                cur = cur.right

    def find(self, value):
        father = None
        cur = self.root
        while cur.value != value:
            father = cur
            if value < cur.value:
                cur = cur.left
            elif value > cur.value:
                cur = cur.right
            if cur == None:
                return False, None, None
        return True, cur, father

    def delete(self, value):
        if self.find(value)[0] == False:
            # 如果不存在,直接返回
            return None
        p = self.root
        if value < p.value:
            cur = p.left
        elif value > p.value:
            cur = p.right
        else:
            # 当要删的是根节点
            cur = p
            if cur.left == None and cur.right == None:
                # 如果根节点没有左右子树,直接把根节点指向空
                self.root = None
                return None
            if cur.left == None or cur.right == None:
                # 如果只有一个子树
                if cur.left == None:
                    # 如果只有右子树,找到右子树的最左的位置
                    cur = cur.right
                    while cur.left != None:
                        p = cur
                        cur = cur.left
                    if p == self.root:
                        # 如果右子树最左位置的父节点还是根节点,代表右孩子就是右子树最左的位置,把根节点指向右孩子
                        self.root = cur
                        return self.root
                    p.left = cur.right  # 把右子树最左位置的右子树接到它父节点的左树上
                    cur.right = self.root.right  # 把根节点的右孩子接到右子树最左位置的右孩子上
                    self.root = cur
                    return p
                else:
                    # 如果只有左子树,找到左子树最右的位置
                    cur = cur.left
                    while cur.right != None:
                        p = cur
                        cur = cur.right
                    if p == self.root:
                        # 如果左子树最右位置的父节点还是根节点,就代表左孩子就是左子树最右的位置,把根节点指向左孩子
                        self.root = cur
                        return self.root
                    p.right = cur.left  # 把左子树最右位置的左子树接到它的父节点的右树上
                    cur.left = self.root.left  # 把根节点的左孩子接到左子树最右位置的左孩子的上
                    self.root = cur
                    return p
            else:
                # 左右孩子双全,随便选一种。
                # 找到左子树最右的位置
                cur = cur.left
                while cur.right != None:
                    p = cur
                    cur = cur.right
                if p == self.root:
                    # 如果左子树最右位置的父节点还是根节点,就代表左孩子就是左子树最右的位置,把根节点的右孩子接到左孩子的右树上,把根节点指向左孩子
                    cur.right = self.root.right
                    self.root = cur
                    return self.root
                p.right = cur.left  # 把左子树最右位置的左子树接到它的父节点的右树上
                cur.left = self.root.left  # 把根节点的左孩子接到左子树最右位置的左孩子的上
                cur.right = self.root.right  # 把根节点的右孩子接到左子树最右位置的右孩子的上
                self.root = cur
                return p
        while cur.value != value:
            # 往下找到要删除的节点cur
            p = cur
            if value < cur.value:
                cur = cur.left
            elif value > cur.value:
                cur = cur.right
        if cur.left == None and cur.right == None:
            # 如果cur没有左右子树,把p对应的方向指向空
            if p.left == cur:
                p.left = None
            else:
                p.right == None
            return p
        if cur.left == None or cur.right == None:
            # 如果只有一个子树
            if cur.right != None:
                # 如果cur没有左子树,找到右树最左的位置
                p2 = cur
                cur2 = cur.right
                while cur2.left != None:
                    p2 = cur2
                    cur2 = cur2.right
                if p2 == cur:
                    # 如果右树最左位置的父节点还是cur,代表右孩子就是右树最左的位置,把p对应的方向改成右孩子
                    if p.left == cur:
                        p.left = cur2
                    elif p.right == cur:
                        p.right = cur2
                    return p2
                p2.left = cur2.right  # 把右树最左位置的右子树接到它父节点的左孩子上
                cur2.left = cur.left  # 把cur的左子树(None)接到右树最左位置的左孩子上
                cur2.right = cur.right  # 把cur的右子树接到右树最左位置的右孩子上
                if p.left == cur:
                    p.left = cur2
                else:
                    p.right = cur2
                return
            if cur.left != None:
                # 如果cur没有右子树,找到左树最右的位置
                p2 = cur
                cur2 = cur.left
                while cur2.right != None:
                    p2 = cur2
                    cur2 = cur2.right
                if p2 == cur:
                    # 如果左树最右位置的父节点还是cur,代表左孩子就是左树最右的位置,把p对应的方向改成左孩子
                    if p.left == cur:
                        p.left = cur2
                    else:
                        p.right = cur2
                    return
                p2.right = cur2.left  # 把左树最右位置的左子树接到它父节点的左孩子上
                cur2.left = cur.left  # 把cur的左子树接到左树最右位置的左孩子上
                cur2.right = cur.right  # 把cur的右子树(None)接到左树最右位置的右孩子上
                if p.left == cur:
                    p.left = cur2
                else:
                    p.right = cur2
                return
        else:
            # 左右孩子双全,随便选一种
            # 找到右子树最左的位置
            p2 = cur
            cur2 = cur.right
            while cur2.left != None:
                p2 = cur2
                cur2 = cur2.right
            if p2 == cur:
                # 如果右树最左位置的父节点还是cur,代表右孩子就是右树最左的位置,把cur的左树接到右树最左位置的左孩子上,把p对应的方向改成右孩子
                cur2.left = cur.left
                if p.left == cur:
                    p.left = cur2
                else:
                    p.right = cur2
                return
            p2.left = cur2.right  # 把右树最左位置的右子树接到它父节点的左孩子上
            cur2.left = cur.left  # 把cur的左子树接到右树最左位置的左孩子上
            cur2.right = cur.right  # 把cur的右子树接到右树最左位置的右孩子上
            if p.left == cur:
                p.left = cur2
            else:
                p.right = cur2
            return

    def simple_delete(self, value):
        found = self.find(value)
        cur = found[1]
        father = found[2]
        if found[0] == False:
            return None
        if father == None:
            if cur.left == None and cur.right == None:
                self.root = None
                return None
            elif cur.left == None or cur.right == None:
                if cur.left == None:
                    cur2 = cur.right
                    while cur2.left != None:
                        cur2 = cur2.left
                    if cur2 == cur.right:
                        self.root = cur2
                        return cur2
                    else:
                        found_cur2 = self.find(cur2.value)
                        cur2_father = found_cur2[2]
                        cur2_father.left = cur2.right
                        cur2.right = cur.right
                        self.root = cur2
                else:
                    cur2 = cur.left
                    while cur2.right != None:
                        cur2 = cur2.right
                    if cur2 == cur.left:
                        self.root = cur2
                        return cur2
                    else:
                        found_cur2 = self.find(cur2.value)
                        cur2_father = found_cur2[2]
                        cur2_father.right = cur2.left
                        cur2.left = cur.left
                        self.root = cur2
                return cur2_father

            else:
                cur2 = cur.right
                while cur2.left != None:
                    cur2 = cur2.left
                if cur2 == cur.right:
                    cur2.left = cur.left
                    self.root = cur2
                    return cur2
                else:
                    found_cur2 = self.find(cur2.value)
                    cur2_father = found_cur2[2]
                    cur2_father.left = cur2.right
                    cur2.right = cur.right
                    cur2.left = cur.left
                    self.root = cur2
                return cur2_father
        else:
            if cur.left == None and cur.right == None:
                if cur == father.left:
                    father.left = None
                elif cur == father.right:
                    father.right = None
                return father
            elif cur.left == None or cur.right == None:
                if cur.left == None:
                    cur2 = cur.right
                    while cur2.left != None:
                        cur2 = cur2.left
                    if cur2 == cur.right:
                        if cur == father.left:
                            father.left = cur2
                        elif cur == father.right:
                            father.right = cur2
                        return cur2
                    else:
                        found_cur2 = self.find(cur2.value)
                        cur2_father = found_cur2[2]
                        cur2_father.left = cur2.right
                        cur2.right = cur.right
                        if cur == father.left:
                            father.left = cur2
                        elif cur == father.right:
                            father.right = cur2
                        return cur2_father
                else:
                    cur2 = cur.left
                    while cur2.right != None:
                        cur2 = cur2.right
                    if cur2 == cur.left:
                        if cur == father.left:
                            father.left = cur2
                        elif cur == father.right:
                            father.right = cur2
                        return cur2
                    else:
                        found_cur2 = self.find(cur2.value)
                        cur2_father = found_cur2[2]
                        cur2_father.right = cur2.left
                        cur2.left = cur.left
                        if cur == father.left:
                            father.left = cur2
                        elif cur == father.right:
                            father.right = cur2
                    return cur2_father
            else:
                cur2 = cur.left
                while cur2.right != None:
                    cur2 = cur2.right
                if cur2 == cur.left:
                    cur2.right = cur.right
                    if cur == father.left:
                        father.left = cur2
                    elif cur == father.right:
                        father.right = cur2
                    return cur2
                else:
                    found_cur2 = self.find(cur2.value)
                    cur2_father = found_cur2[2]
                    cur2_father.right = cur2.left
                    cur2.left = cur.left
                    cur2.right = cur.right
                    if cur == father.left:
                        father.left = cur2
                    elif cur == father.right:
                        father.right = cur2
                return cur2_father

    def select(self):
        res = []
        queue = []
        queue.append(self.root)
        while queue != []:
            root = queue.pop(0)
            if root != None:
                res.append(root)
                queue.append(root.left)
                queue.append(root.right)
            else:
                res.append("#")
        return res

    def __repr__(self):
        return str(self.select())


# 平衡性:为了防止数据情况不好破坏性能和指标,左树和右树的节点体量相差不要太悬殊,左树和右树高度差不超过k(不同结构k不同)
# AVL树是平衡性要求最严格的,它左树和右树的高度差不超过1
# 调整平衡性的方法:
#     1.左旋:整个树向左倒,让原头节点的右孩子作为头节点,新头节点的左孩子放到原头节点的右树上,原头节点变成新头节点的新左孩子
#     2.右旋:整个树向右倒,让原头节点的左孩子作为头节点,新头节点的右孩子放到原头节点的左树上,原头节点变成新头节点的新右孩子
class Balance(object):
    def Turn_left(self, head, father):
        if head.right == None:
            # 如果没有右子树,不能左旋
            return
        newhead = head.right  # 新头节点是原头节点的右孩子
        head.right = newhead.left  # 把原头节点的右孩子替换成新头节点的左树
        newhead.left = head  # 把新头节点的左孩子替换成原头节点
        if father == None:
            # 如果要左旋的是整个树,让根节点指向新头节点
            self.root = newhead
        elif father.left == head:
            # 把新头节点接在父节点的下面
            father.left = newhead
        else:
            father.right = newhead

    def Turn_right(self, head, father):
        if head.left == None:
            return
        newhead = head.left
        head.left = newhead.right
        newhead.right = head
        if father == None:
            self.root = newhead
        elif father.left == head:
            father.left = newhead
        else:
            father.right = newhead


# 怎么使用左旋和右旋让树拥有平衡性?
#     一、什么时候检查平衡性?
#             1.增:从新增节点开始往上检查,当前节点所在的树有没有平衡性
#             2.删:从替换节点的父节点开始往上检查,当前节点所在的树有没有平衡性
#     二、怎么检查平衡性,怎么检查平衡性?    (记住LL型和RR型怎么操作,其他两种的策略就是转换成这样的结构)
#             1.LL型: 左孩子的左树过长导致平衡性失效,右旋
#             2.LR型: 左孩子的右树过长导致平衡性失效,左孩子左旋,再左旋
#             3.RR型: 右孩子的右树过长导致平衡性失效,左旋
#             4.RL型: 右孩子的左树过长导致平衡性失效,右孩子右旋,再左旋
class AVL(object):
    def __init__(self):
        self.Tree = BST()

    def add(self, value):
        self.Tree.add(value)
        found = self.Tree.find(value)
        node = found[1]
        father = found[2]
        self.balance(node, father)

    def select(self):
        return self.Tree.select()

    def find(self, node):
        if type(node) == int:
            return self.Tree.find(node)
        if node == None:
            return False, None, None
        value = node.value
        return self.Tree.find(value)

    def delete(self, value):
        node = self.Tree.simple_delete(value)
        found = self.find(node)
        node = found[1]
        father = found[2]
        self.balance(node, father)
        return node

    def height(self, node):
        if node == None:
            return 0
        leftHeight = self.height(node.left)
        rightHeight = self.height(node.right)
        height = max(leftHeight, rightHeight) + 1
        return height

    def balance(self, node, father):
        while node != None:
            nodeBalance = self.height(node.left) - self.height(node.right)
            if nodeBalance >= 2:
                leftBalance = self.height(node.left.left) - self.height(node.left.right)
                if leftBalance >= 0:
                    # 左树过长,LL
                    Balance.Turn_right(self.Tree, node, father)
                else:
                    # LR 
                    Balance.Turn_left(self.Tree, node.left, node)
                    Balance.Turn_right(self.Tree, node, father)

            elif nodeBalance <= -2:
                rightBalance = self.height(node.right.right) - self.height(node.right.left)
                if rightBalance >= 0:
                    # 右树过长,RR
                    Balance.Turn_left(self.Tree, node, father)
                else:
                    # RL
                    Balance.Turn_right(self.Tree, node.right, node)
                    Balance.Turn_left(self.Tree, node, father)
            father_father = self.find(father)
            node = father_father[1]
            father = father_father[2]

    def __repr__(self):
        return str(self.select())


# 红黑树和SB树
# 这两个和AVL树的区别就是平衡的标准不同.
#     1.AVL树: 左树和右树高度相差不超过1
#     2.SB树: 每一颗树的大小要大于等于其兄弟树的子树大小 (如果左树大小为10,则右树大小最大为10+10+1)
#     3.红黑树:  如果一条路最长就是黑红相间,最短就是全黑,所以从当前点出发,每一条路径长度不超过两倍
#         ① 点的标签(红、黑)
#         ② 整棵树的头和叶节点的子节点(None)都是黑
#         ③ 红点不相邻
#         ④ 每一条到结束的路径黑点一样多


# SB树
#    T
# L     R
# A B   C D
# LL型:左子树的左边大小过大,即R<A,右旋。L变为头节点,因为R的孩子没有变化,T增加新的孩子节点B,L的右孩子变化,所以再判断T和L的情况
# RR型:右子树的右边大小过大,即L<D,左旋。调节T和R的平衡
# LR型:左子树的右边大小过大,即R<B,先L左旋再T右旋,把B调整到头节点位置。调节L、T的平衡再调节B的平衡
#      T                   T                 B
#  L       R           B       R         L       T
# A   B   C   D  -->  L   F   C   D  -->A   E   F   R
#   E F             A E                           C D
#
# RL型:右子树的左边大小过大,即L<C.先R右旋再T左旋,把C调节到头节点。调节R、T的平衡再调节C的平衡


# 跳表
# 跳表的结构和前面三种都不一样,它是由多条链表组成的一个类似于网状的结构

# 每加入一个节点的时候,按照随机的方式添加层数。
# 所有操作都是从高层开始,查找比value小的最右的节点,修改这个节点的next就相当于修改了表的结构
# 因为增加一层的概率是1/2,增加两层的概率就是1/4.....第0层右N个节点,第1层大概N/2个节点,第2层大概N/4个节点,
# 它的每一层都能加速掉1/2、1/4...个节点
class SkipNode(object):
    def __init__(self, value):
        self.value = value
        self.next = [None]

    def add(self, num):
        self.next += [None] * num

    def __repr__(self):
        return str(self.value)


class Skip_List(object):
    def __init__(self):
        self.root = SkipNode(None)

    def find(self, node, value, index):
        # 找到在index层从node点开始,小于value最右的位置
        while True:
            if node.next[index] == None or node.next[index].value >= value:
                break
            node = node.next[index]
        return node

    def exist(self, value):
        # 查找是否存在,返回小于value最高最右的节点,以及查找到的节点的当前层数
        index = len(self.root.next) - 1
        cur = self.root
        while index >= 0:
            node = self.find(cur, value, index)
            cur = node
            if cur.next[index] != None and cur.next[index].value == value:
                return True, cur, index
            index -= 1
        return False, None, -1

    def insert(self, value):
        n = 0
        while True:
            if random.randint(0, 1) == 1:
                n += 1
            else:
                break
        print(n)
        node = SkipNode(value)
        node.add(n)
        if n + 1 > len(self.root.next):
            self.root.add(n + 1 - len(self.root.next))
        index = len(self.root.next) - 1
        cur = self.root
        while index >= 0:
            while True:
                if cur.next[index] == None or cur.next[index].value > value:
                    if index <= n:
                        node.next[index] = cur.next[index]
                        cur.next[index] = node
                    break
                cur = cur.next[index]
            index -= 1

    def delete(self, value):
        found = self.exist(value)
        if found[0] == False:
            return
        cur = found[1]
        index = found[2]
        cur.next[index] = cur.next[index].next[index]
        if cur == self.root and cur.next[index] == None:
            cur.next.pop()
        index -= 1
        while index >= 0:
            cur = self.find(cur, value, index)
            cur.next[index] = cur.next[index].next[index]
            if cur == self.root and cur.next[index] == None:
                cur.next.pop()
            index -= 1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值