Python实现:链表、队列、堆栈、AVL树、红黑树

一、链表

class Node(object):
    def __init__(self, value):
        # 元素域
        self.value = value
        # 链接域
        self.next = None


class LinkedListOneway(object):
    def __init__(self, node=None):
        self.__head = node

    def __len__(self):
        # 游标,用来遍历链表
        cur = self.__head
        # 记录遍历次数
        count = 0
        # 当前节点为None则说明已经遍历完毕
        while cur:
            count += 1
            cur = cur.next
        return count

    def is_empty(self):
        # 头节点不为None则不为空
        return self.__head == None

    def add(self, value):
        """
        头插法
        先让新节点的next指向头节点
        再将头节点替换为新节点
        顺序不可错,要先保证原链表的链不断,否则头节点后面的链会丢失
        """
        node = Node(value)
        node.next = self.__head
        self.__head = node

    def append(self, value):
        """尾插法"""
        node = Node(value)
        cur = self.__head
        if self.is_empty():
            self.__head = node
        else:
            while cur.next:
                cur = cur.next
            cur.next = node

    def insert(self, pos, value):
        # 应对特殊情况
        if pos <= 0:
            self.add(value)
        elif pos > len(self) - 1:
            self.append(value)
        else:
            node = Node(value)
            prior = self.__head
            count = 0
            # 在插入位置的前一个节点停下
            while count < (pos - 1):
                prior = prior.next
                count += 1
            # 先将插入节点与节点后的节点连接,防止链表断掉,先链接后面的,再链接前面的
            node.next = prior.next
            prior.next = node

    def remove(self, value):
        cur = self.__head
        prior = None
        while cur:
            if value == cur.value:
                # 判断此节点是否是头节点
                if cur == self.__head:
                    self.__head = cur.next
                else:
                    prior.next = cur.next
                break
            # 还没找到节点,有继续遍历
            else:
                prior = cur
                cur = cur.next

    def search(self, value):
        cur = self.__head
        while cur:
            if value == cur.value:
                return True
            cur = cur.next
        return False

    def traverse(self):
        cur = self.__head
        while cur:
            print(cur.value)
            cur = cur.next

二、队列

class  Queue:
    #初始化队列
    def __init__(self):
        self.items=[]

    #加入队列
    def inqueue(self,item):
        self.items.append(item)
    #出队列
    def dequeue(self):
        return self.items.pop(0)
        
    #判断是否为空
    def empty(self):
        return self.size()==0
    #返回长度
    def size(self):
        return len(self.items)
附个实例:约瑟夫斯问题
#约瑟夫斯问题
def josephus(namelist, num):
    simqueue = Queue()
    for name in namelist:
        simqueue.inqueue(name)

    while simqueue.size() > 1:
        for i in range(num):
            simqueue.inqueue(simqueue.dequeue())
        simqueue.dequeue()
    return simqueue.dequeue()

def josephus(namelist,num):
    squeue = Queue()
    for name in namelist:
        squeue.inqueue(name)

    while squeue.size()>1:
        for i in range(num):
            squeue.inqueue(squeue.dequeue())
        squeue.dequeue()
    return squeue.dequeue()

if __name__ == '__main__':
    print(josephus(["Java", "Python", "C++", "C", "PHP", "Html5"], 5))


三、堆栈

# 后进先出
class Stack():
    def __init__(self,size):
        self.size=size
        self.stack=[]
        self.top = -1
    # 压入数据
    def push(self,x):
        if self.isfull():
            raise eecception("栈满...")
        else:
            self.stack.append(x)
            self.top = self.top + 1

    # 弹出数据
    def pop(self):
        if self.isempty():
            raise exception("栈空...")
        else:
            self.top = self.top -1
            self.stack.pop()

    def isfull(self):
        return self.top+1 == self.size

    def isempty(self):
        return self.top == '-1'
        
    def showStack(self):
        print(self.stack)
 
if __name__ == "__main__":
    s=Stack(10)
    for i in range(10):
        s.push(i)
    s.showStack()
    for i in range(3):
        s.pop()
    s.showStack()
 
"""
类中有top属性,用来指示栈的存储情况,初始值为1,一旦插入一个元素,其值加1,利用top的值乐意判定栈是空还是满。
执行时先将0,1,2,3,4依次入栈,然后删除栈顶的前三个元素
"""

四、AVL树(平衡二叉树)

详细关于AVL树请阅读:浅谈【树】:红黑树、AVL树、B树、B+树

class Node(object):
    def __init__(self, key, parent=None, left=None, right=None):
        self.key = key          # 存储的数据
        self.parent = parent    # 父节点
        self.left = left        # 左孩子节点
        self.right = right      # 右孩子节点
        self.bf = 0             # 平衡因子 等于左子树高度减去右子树高度

    def l_rotate(self, par, cur):
        """
        左单旋转
        :param par:  平衡因子为2|-2的节点
        :param cur:  作为轴心旋转的节点(平衡因子不为2)
        :return: None
        """
        p = cur.left                    # 辅助引用p指向cur的左节点
        cur.left = par                  # cur的左节点指向par
        par.right = p                   # par的右节点指向cur的左节点
        if p:
            p.parent = par              # cur的左节点不为空时更新该节点的父节点
        if par == self.root:
            self.root = cur             # 判断平衡因子为2的par是否为根
        else:
            if par == par.parent.left:  # 更新par父节点的子节点信息
                par.parent.left = cur
            else:
                par.parent.right = cur
        cur.parent = par.parent         # 当前cur的父节点指向原来par的父节点
        par.parent = cur                # par变为cur的左子节点
        cur.bf = par.bf = 0             # 插入操作中, 操作的两个节点旋转后平衡因子恢复为0

    def r_rotate(self, par, cur):
        """右单旋转"""
        p = cur.right
        cur.right = par
        par.left = p
        if p:
            p.parent = par
        if par == self.root:
            self.root = cur
        else:
            if par == par.parent.left:
                par.parent.left = cur
            else:
                par.parent.right = cur

        cur.parent = par.parent         # 更新父节点信息
        par.parent = cur
        cur.bf = par.bf = 0             # 更新平衡因子

    def lr_rotate(self, par, cur):
        """左右双旋转"""
        # 先左旋转 cur 和 cur的右子节点
        cur_right = cur.right           # 获得cur的右子节点的引用
        bf = cur_right.bf
        self.l_rotate(cur, cur_right)
        # 继续右旋转
        self.r_rotate(par, cur_right)
        if bf == 0:                     # 根据cur_right的平衡因子更新操作的3个节点
            cur.bf = cur_right.bf = par.bf = 0
        elif bf == -1:
            par.bf = 1
            cur.bf = cur_right.bf = 0
        else:
            cur.bf = -1
            cur_right.bf = par.bf = 0
            
    def rl_rotate(self, par, cur):
        """右左双旋转"""
        # 先右旋转 cur 和 cur的左子节点
        cur_left = cur.left                         # 获得cur的右子节点的引用
        bf = cur_left.bf
        self.r_rotate(cur, cur_left)
        self.l_rotate(par, cur_left)                # 继续右旋转       
        if bf == 0:                                 # 根据cur_left的平衡因子更新操作的3个节点
            cur.bf = cur_left.bf = par.bf = 0
        elif bf == -1:
            cur.bf = 1
            par.bf = cur_left.bf = 0
        else:
            par.bf = -1
            cur_left.bf = cur.bf = 0
            
    def find(self, key):
        """寻找键值"""
        p = self.root
        while p:
            if p.key == key:
                return p
            if key < p.key:
                p = p.left
            else:
                p = p.right
        return None

五、红黑树

详细关于红黑树请阅读:浅谈【树】:红黑树、AVL树、B树、B+树

#定义红黑树
class RBTree(object):
    def __init__(self):
        self.nil = RBTreeNode(0)
        self.root = self.nil

class RBTreeNode(object):
    def __init__(self, x):
        self.key = x
        self.left = None
        self.right = None
        self.parent = None
        self.color = 'black'
        self.size=None

#左旋转
def LeftRotate( T, x):
    y = x.right
    x.right = y.left
    if y.left != T.nil:
        y.left.parent = x
    y.parent = x.parent
    if x.parent == T.nil:
        T.root = y
    elif x == x.parent.left:
        x.parent.left = y
    else:
        x.parent.right = y
    y.left = x
    x.parent = y

#右旋转
def RightRotate( T, x):
    y = x.left
    x.left = y.right
    if y.right != T.nil:
        y.right.parent = x
    y.parent = x.parent
    if x.parent == T.nil:
        T.root = y
    elif x == x.parent.right:
        x.parent.right = y
    else:
        x.parent.left = y
    y.right = x
    x.parent = y

#红黑树的插入
def RBInsert( T, z):
    y = T.nil
    x = T.root
    while x != T.nil:
        y = x
        if z.key < x.key:
            x = x.left
        else:
            x = x.right
    z.parent = y
    if y == T.nil:
        T.root = z
    elif z.key < y.key:
        y.left = z
    else:
        y.right = z
    z.left = T.nil
    z.right = T.nil
    z.color = 'red'
    RBInsertFixup(T, z)
    return z.key, '颜色为', z.color


#红黑树的上色
def RBInsertFixup( T, z):
    while z.parent.color == 'red':
        if z.parent == z.parent.parent.left:
            y = z.parent.parent.right
            if y.color == 'red':
                z.parent.color = 'black'
                y.color = 'black'
                z.parent.parent.color = 'red'
                z = z.parent.parent
            else:
                if z == z.parent.right:
                    z = z.parent
                    LeftRotate(T, z)
                z.parent.color = 'black'
                z.parent.parent.color = 'red'
                RightRotate(T,z.parent.parent)
        else:
            y = z.parent.parent.left
            if y.color == 'red':
                z.parent.color = 'black'
                y.color = 'black'
                z.parent.parent.color = 'red'
                z = z.parent.parent
            else:
                if z == z.parent.left:
                    z = z.parent
                    RightRotate(T, z)
                z.parent.color = 'black'
                z.parent.parent.color = 'red'
                LeftRotate(T, z.parent.parent)
    T.root.color = 'black'


def RBTransplant( T, u, v):
    if u.parent == T.nil:
        T.root = v
    elif u == u.parent.left:
        u.parent.left = v
    else:
        u.parent.right = v
    v.parent = u.parent


def RBDelete(T, z):
    y = z
    y_original_color = y.color
    if z.left == T.nil:
        x = z.right
        RBTransplant(T, z, z.right)
    elif z.right == T.nil:
        x = z.left
        RBTransplant(T, z, z.left)
    else:
        y = TreeMinimum(z.right)
        y_original_color = y.color
        x = y.right
        if y.parent == z:
            x.parent = y
        else:
            RBTransplant(T, y, y.right)
            y.right = z.right
            y.right.parent = y
        RBTransplant(T, z, y)
        y.left = z.left
        y.left.parent = y
        y.color = z.color
    if y_original_color == 'black':
        RBDeleteFixup(T, x)


#红黑树的删除
def RBDeleteFixup( T, x):
    while x != T.root and x.color == 'black':
        if x == x.parent.left:
            w = x.parent.right
            if w.color == 'red':
                w.color = 'black'
                x.parent.color = 'red'
                LeftRotate(T, x.parent)
                w = x.parent.right
            if w.left.color == 'black' and w.right.color == 'black':
                w.color = 'red'
                x = x.parent
            else:
                if w.right.color == 'black':
                    w.left.color = 'black'
                    w.color = 'red'
                    RightRotate(T, w)
                    w = x.parent.right
                w.color = x.parent.color
                x.parent.color = 'black'
                w.right.color = 'black'
                LeftRotate(T, x.parent)
                x = T.root
        else:
            w = x.parent.left
            if w.color == 'red':
                w.color = 'black'
                x.parent.color = 'red'
                RightRotate(T, x.parent)
                w = x.parent.left
            if w.right.color == 'black' and w.left.color == 'black':
                w.color = 'red'
                x = x.parent
            else:
                if w.left.color == 'black':
                    w.right.color = 'black'
                    w.color = 'red'
                    LeftRotate(T, w)
                    w = x.parent.left
                w.color = x.parent.color
                x.parent.color = 'black'
                w.left.color = 'black'
                RightRotate(T, x.parent)
                x = T.root
    x.color = 'black'


def TreeMinimum( x):
    while x.left != T.nil:
        x = x.left
    return x

    
#中序遍历
def Midsort(x):
    if x!= None:
        Midsort(x.left)
        if x.key!=0:
            print('key:', x.key,'x.parent',x.parent.key)
        Midsort(x.right)

if __name__ == "__main__":   
    nodes = [11,2,14,1,7,15,5,8,4]
    T = RBTree()
    for node in nodes:
        print('插入数据',RBInsert(T,RBTreeNode(node)))
    print('中序遍历')
    Midsort(T.root)
    RBDelete(T,T.root)
    print('中序遍历')
    Midsort(T.root)
    RBDelete(T,T.root)
    print('中序遍历')
    Midsort(T.root)


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容