數據結構


 

 

  • 數據結構是指相互之間存在着一種或多種關係的數據元素的結合和該集合中數據元素之間的關係組成。

  • 簡單來講,數據結構就是設計數據 以何種方式組織並存儲在計算機中

  • 例如:列表、集合與字典等都是一種數據結構。

  • N.Wirth:"程序=數據結構+算法"

數據結構的分類

數據機構按照其邏輯結構可分爲線性結構、樹結構、圖結構node

  1. 線性結構:數據結構中的元素存在一對一的相互關係
  2. 樹結構:數據結構中的元素存在一對多的相互關係
  3. 圖結構:數據結構中的元素存在多對多的相互關係

 

一、列表/數組

列表(其它語言是數組)是一種基本數據類型。
python

關於列表問題:算法

  一、列表的元素是如何存儲的?(存內存地址(64位機器固定8bytes))數組

  二、如何查找元素?(從列表起始位置的內存地址,查第幾個元素就起始位置加n*8)數據結構

  三、列表不用顯示聲明長度?(python內部經過完整拷貝來調整列表長度)app

 

二、棧

棧(Stack)是一個數據集合,能夠理解爲只能在一端進行插入或刪除操做的列表。dom

棧的特色:後進先出 LIFOide

棧的概念:棧頂,棧底函數

棧的基本操做:post

  • 進棧(壓棧):push
  • 出棧:pop
  • 取棧頂:gettop

棧的實現

 使用通常的列表便可實現棧

  • 進棧:li.append
  • 出棧:li.pop
  • 取棧頂:li[-1]
class Stack:

    def __init__(self):
        self.stack = []

    def push(self, data):
        self.stack.append(data)

    def pop(self):
        return self.stack.pop()

    def get_top(self):
        if len(self.stack) > 0:
            return self.stack[-1]
        else:
            return None

    def is_empty(self):
        return len(self.stack) > 0

棧的應用 -- 括號匹配問題

 括號匹配問題:給一個字符串,其中包括小括號、中括號、大括號,求該字符串中的括號是否匹配。

例如:

    • ()()[]{}  匹配
    • ([{()}])  匹配
    • [](             不匹配
    • ([)]            不匹配
def brace_match(s):
    match = {'}': '{', ']': '[', ')': '('}
    stack = Stack()
    for ch in s:
        if ch in {'(', '[', '{'}:
            stack.push(ch)
        else:   # ch in {'}',']',')'}
            if stack.is_empty():
                return False
            elif stack.get_top() == match[ch]:
                stack.pop()
            else:
                return False

    if stack.is_empty():
        return True
    else:
        return False


print(brace_match('[{()}(){()}[]({}){}]'))
print(brace_match('[]}'))
View Code

 

三、隊列

隊列(queue)是一個數據集合,僅容許在列表的一端進行插入,另外一端進行刪除。

  • 進行插入的一點稱爲隊尾(rear),插入動做成爲進隊或入隊。
  • 進行刪除的的一端稱爲對頭(front),刪除動做稱爲出隊。
  • 隊列的性質:先進先出(First-in, First-out)

隊列的實現

初步設想:列表+兩個下標指針

建立一個列表和兩個變量,front變量指向隊首,rear變量指向隊尾。初始時,front和rear都爲0

進隊操做:元素寫到li[rear]的位置,rear自增1

出隊操做:返回li[front]的元素,front自增1

出現d的狀況後,隊列沒法繼續添加元素,可是列表裏面有位置是空的,這一點很是很差

隊列的實現原理 -- 環形隊列

環形隊列:當隊尾指針front == Maxsize + 1時,再前進一個位置就自動到0

 實現方式:求餘運算

隊首指針前進1:front = (front+1) % maxsize

隊尾指針前進1:rear = (rear+1) % maxsize

隊空條件:rear == front隊滿條件:(rear+1)% maxsize == front

class Queue:
    def __init__(self, size=100):
        self.queue = [0 for i in range(size)]
        self.size = size
        self.rear = 0   # 隊尾指針
        self.front = 0  # 隊首指針

    def push(self, element):
        if not self.is_filled():
            self.rear = (self.rear + 1) % self.size
            self.queue[self.rear] = element
        else:
            raise IndexError("Queue is filled.")

    def pop(self):
        if not self.is_empty():
            self.front = (self.front + 1) % self.size
            return self.queue[self.front]
        else:
            raise IndexError("Queue is empty.")

    # 判斷隊空
    def is_empty(self):
        return self.rear == self.front

    # 判斷隊滿
    def is_filled(self):
        return (self.rear + 1) % self.size == self.front


q = Queue(5)
for i in range(4):
    q.push(i)
print(q.pop())
q.push(4)
View Code

隊列的內置模塊

使用方法:from collections import deque

建立隊列:queue = deque(li)

進隊:append

出隊:popleft

雙向隊列隊首進隊:appendleft

雙向隊列隊尾進隊:pop

棧和隊列的應用 -- 迷宮問題

解決方法1:棧--深度優先搜索(回溯法)

思路:從一個節點開始,任意找下一個能走的點,當找不到能走的點時,退回上一個點尋找是否有其餘方向的點。
(使用棧存儲當前路徑)
maze = [
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [1, 0, 0, 1, 0, 0, 0, 1, 0, 1],
    [1, 0, 0, 1, 0, 0, 0, 1, 0, 1],
    [1, 0, 0, 0, 0, 1, 1, 0, 0, 1],
    [1, 0, 1, 1, 1, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 1, 0, 0, 0, 0, 1],
    [1, 0, 1, 0, 0, 0, 1, 0, 0, 1],
    [1, 0, 1, 1, 1, 0, 1, 1, 0, 1],
    [1, 1, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
]

dirs = [
    lambda x, y: (x+1, y),
    lambda x, y: (x, y+1),
    lambda x, y: (x-1, y),
    lambda x, y: (x, y-1)
]


def maze_path(x1, y1, x2, y2):
    stack = []
    stack.append((x1, y1))
    while len(stack) > 0:
        curNode = stack[-1]     # 當前節點
        if curNode[0] == x2 and curNode[1] == y2:
            # 走到終點了
            for p in stack:
                print(p)
            return True

        # x,y 四個方向  x+1, y; x, y+1; x-1, y; x, y-1
        for dir in dirs:
            next_Node = dir(curNode[0], curNode[1])
            # 若是下一個節點能走
            if maze[next_Node[0]][next_Node[1]] == 0:
                stack.append(next_Node)
                maze[next_Node[0]][next_Node[1]] = 2
                break
        else:   # 一個都找不到
            maze[next_Node[0]][next_Node[1]] = 2
            stack.pop()
    else:
        print('沒有路')
        return False

maze_path(1,1,8,8)
View Code

 

四、鏈表

鏈表是由一系列節點組成的元素集合。每一個元素包含兩部分,數據域item和指向下一個節點的指針next。經過節點之間的相互鏈接,最終串聯稱一個鏈表。

 建立鏈表

 

class Node:
    def __init__(self, data):
        self.data = data
        self.next = None


# 頭插法
def create_linklist(li):
    head = Node(li[0])
    for num in li[1:]:
        node = Node(num)
        node.next = head
        head = node
    return head

# 尾插法
def create_taillist(li):
    head = Node(li[0])
    tail = head
    
    for num in li:
        node = Node(num)
        tail.next = node
        tail = node
    return head

# 鏈表的遍歷
def print_link(lk):
    while lk:
        print(lk.data, end=',')
        lk = lk.next
View Code

鏈表節點的插入和刪除

插入:

p.next = curNode.next
curNode.next = p

刪除:

 curNode.next=p.next

 del p

 

雙鏈表

雙鏈表的每一個節點有兩個指針:一個指向後一個節點,另外一個指向前一個節點(單鏈表只有next)

雙鏈表的插入和刪除

插入:

  p.next = curNode.next

  curNode.next.prior = p

  p.prior = curNode

  curNode.next = p

刪除:

  curNode.next = p.next

  p.next.prior = curNode

  del p

鏈表與順序表

  • 鏈表在插入和刪除的操做上明顯快於順序表
  • 鏈表的內存能夠更靈活的分配

 

五、哈希表

哈希表是一個經過哈希函數來計算數據存儲位置的數據結構,一般支持以下操做:

  1. insert(key, value):插入鍵值對(key,value)
  2. get(key):若是存在鍵值對則返回其value,不然返回空值
  3. delete(key):刪除鍵爲key的鍵值對

知識儲備-- 直接尋址表

當關鍵字的全域U比較小時,直接尋址表是一種簡單而有效的方法

直接尋址技術缺點:

  • 當域U很大時,須要消耗大量內存,很不實際
  • 若是域很大而實際出現的key很小,則大量空間被浪費
  • 沒法處理關鍵字不是數字的狀況

改進直接尋址表:哈希

  • 構建大小爲m的尋址表T
  • key爲k的元素放到h(k)的位置上
  • h(k)是一個函數,其將域U映射到表T[0, 1, ..., m-1]

哈希表(又稱爲散列表),是一種線性表的存儲結構。哈希表由一個直接尋址表和一個哈希函數組成。哈希函數h(k)將元素關鍵字k做爲自變量,返回元素的存儲下標。

假設有一個長度爲7的哈希表,哈希函數h(k)=k%7    元素集合{14, 22, 3, 5}的存儲方式以下圖:

哈希衝突

因爲哈希表的大小是有限的,而要存儲的值的總數量是無限的,由於對於任何哈希函數,都會出現兩個不一樣元素映射到同一個位置上的狀況,這種狀況叫作哈希衝突!

好比h(k)=k%7, h(0)=h(7)=h(14)...

解決哈希衝突的兩個辦法:

一、開放尋執法:若是哈希函數返回的位置已經有值,則能夠向後探查新的位置來存儲這個值。

  • 線性探查:若是位置i被佔用,則探查i+1,i+2,...
  • 二次探查:若是位置i被佔用,則探查則探查i+12,i-12,i+22,i-22,……(2表示平方)
  • 二度哈希:有n個哈希函數,當使用第一個哈希函數h1發生衝突時,則嘗試使用h2,h3,...

二、拉鍊法:哈希表每一個位置都鏈接一個鏈表,當衝突發生時,衝突的元素將被加到該位置鏈表的最後

拉鍊法解決hash衝突代碼實現:

# 鏈表類
class LinkList:
    class Node:
        def __init__(self, item=None):
            self.item = item
            self.next = None

    class LinkListIterator:
        def __init__(self, node):
            self.node = node

        def __next__(self):
            if self.node:
                cur_node = self.node
                self.node = cur_node.next
                return cur_node.item
            else:
                raise StopIteration

        def __iter__(self):
            return self

    def __init__(self, iterable=None):
        self.head = None
        self.tail = None
        if iterable:
            self.extend(iterable)

    def append(self, obj):
        s = LinkList.Node(obj)
        if not self.head:
            self.head = s
            self.tail = s
        else:
            self.tail.next = s
            self.tail = s

    def extend(self, iterable):
        for obj in iterable:
            self.append(obj)

    def find(self, obj):
        for n in self:
            if n == obj:
                return True
        else:
            return False

    def __iter__(self):
        return self.LinkListIterator(self.head)

    def __repr__(self):
        return "<<"+", ".join(map(str, self))+">>"


# 相似於集合的結構
class HashTable:
    def __init__(self, size=101):
        self.size = size
        self.T = [LinkList() for i in range(self.size)]

    def h(self, k):
        return k % self.size

    def insert(self, k):
        i = self.h(k)
        if self.find(k):
            print("Duplicated Insert")
        else:
            self.T[i].append(k)

    def find(self, k):
        i = self.h(k)
        return self.T[i].find(k)


ht = HashTable()

ht.insert(0)
ht.insert(1)
ht.insert(3)
ht.insert(102)
ht.insert(508)

print(",".join(map(str, ht.T)))
print(ht.find(203))
View Code

哈希表 -- 常見哈希函數

除法哈希法:  h(k) = k % m

乘法哈希法:  h(k) = floor(m*(A*Key%1))

全域哈希法:  ha,b(k) = ((a*key + b) mod p) mod m a,b=1,2,...,p-1

哈希表的應用 -- 集合與字典

字典與集合都是經過哈希表來實現的。

a = {'name':xcq, 'age':18, 'gender':'Man'}

使用哈希表存儲字典,經過哈希函數將字典的鍵映射爲下標。假設h('name')=3, h('age'=1),h('gender'=4), 則哈希表存儲爲[Node, 18, Node, 'xcq', 'Man']

若是發生哈希衝突,則經過拉鍊法或則開放尋址法解決。

 

六、二叉樹

樹是一種數據結構 好比:目錄結構

樹是一種能夠遞歸定義的數據結構  樹是由n個節點組成的集合

  若是n=0, 那這是一顆空樹

  若是n>0, 那存在1個節點做爲樹的根節點,其餘節點能夠分爲m個集合,每一個集合自己又是一棵樹

二叉樹:度不超過2的樹(節點最多有兩個叉)

二叉樹的鏈式存儲:

將二叉樹的節點定義爲一個對象,節點之間經過相似鏈表的鏈接方式來鏈接

二叉樹的4種遍歷方式:

 

  1. 前序遍歷:EACBDGF
  2. 中序遍歷:ABCDEGF
  3. 後序遍歷:BDCAFGE
  4. 層次遍歷:EAGCFBD
class BiTreeNode:
    def __init__(self, data):
        self.data = data
        self.lchild = None
        self.rchild = None

a = BiTreeNode("A")
b = BiTreeNode("B")
c = BiTreeNode("C")
d = BiTreeNode("D")
e = BiTreeNode("E")
f = BiTreeNode("F")
g = BiTreeNode("G")

e.lchild = a
e.rchild = g
a.rchild = c
c.lchild = b
c.rchild = d
g.rchild = f

root = e
# 前序遍歷
def pre_order(root):
    if root:
        print(root.data, end=',')
        pre_order(root.lchild)
        pre_order(root.rchild)

# 中序遍歷
def in_order(root):
    if root:
        in_order(root.lchild)
        print(root.data, end=',')
        in_order(root.rchild)

# 後序遍歷
def post_order(root):
    if root:
        post_order(root.lchild)
        post_order(root.rchild)
        print(root.data, end=',')

# 層級遍歷
from collections import deque
def level_order(root):
    que = deque()
    que.append(root)
    while len(que):
        node = que.popleft()
        print(node.data, end=',')
        if node.lchild:
            que.append(node.lchild)
        if node.rchild:
            que.append(node.rchild)
二叉樹的4種遍歷方式

二叉搜索樹

二叉搜索樹是一棵二叉樹且知足性質:設x是二叉樹的一個節點。若是y是x的左子樹的一個節點,那麼y.key <= x.key;若是y是x的右子樹的一個節點,那麼y.key >= x.key

(左邊的都比根節點小,右邊的都比根節點大)

二叉搜索樹的操做:查詢、插入、刪除

須要注意的是刪除操做

刪除操做分3種狀況:

一、若是要刪除的節點是葉子節點:直接刪除

二、若是要刪除的節點只有一個孩子:將此節點的父親與孩子鏈接,而後刪除該節點

三、若是要刪除的節點有兩個孩子:將其右子樹最小節點刪除,並替換當前節點。

二叉搜索樹查詢、插入、刪除代碼實現

import random

class BiTreeNode:
    def __init__(self, data):
        self.data = data
        self.lchild = None   # 左孩子
        self.rchild = None  # 右孩子
        self.parent = None

class BST:
    def __init__(self, li=None):
        self.root = None
        if li:
            for val in li:
                self.insert_no_rec(val)

    # 插入(遞歸)
    def insert(self, node, val):
        if not node:
            node = BiTreeNode(val)
        elif val < node.data:
            node.lchild = self.insert(node.lchild, val)
            node.lchild.parent = node
        elif val > node.data:
            node.rchild = self.insert(node.rchild, val)
            node.rchild.parent = node
        return node

    # 插入(非遞歸)
    def insert_no_rec(self, val):
        p = self.root
        if not p:               # 空樹
            self.root = BiTreeNode(val)
            return
        while True:
            if val < p.data:
                if p.lchild:
                    p = p.lchild
                else:           # 左孩子不存在
                    p.lchild = BiTreeNode(val)
                    p.lchild.parent = p
                    return
            elif val > p.data:
                if p.rchild:
                    p = p.rchild
                else:
                    p.rchild = BiTreeNode(val)
                    p.rchild.parent = p
                    return
            else:
                return

    # 查詢(遞歸)
    def query(self, node, val):
        if not node:
            return None
        if node.data < val:
            return self.query(node.rchild, val)
        elif node.data > val:
            return self.query(node.lchild, val)
        else:
            return node

    # 查詢(非遞歸)
    def query_no_rec(self, val):
        p = self.root
        while p:
            if p.data < val:
                p = p.rchild
            elif p.data > val:
                p = p.lchild
            else:
                return p
        return None

    def pre_order(self, root):
        if root:
            print(root.data, end=',')
            self.pre_order(root.lchild)
            self.pre_order(root.rchild)

    def in_order(self, root):
        if root:
            self.in_order(root.lchild)
            print(root.data, end=',')
            self.in_order(root.rchild)

    def post_order(self, root):
        if root:
            self.post_order(root.lchild)
            self.post_order(root.rchild)
            print(root.data, end=',')


    def __remove_node_1(self, node):
        # 狀況1:node是葉子節點
        if not node.parent:
            self.root = None
        if node == node.parent.lchild:  #node是它父親的左孩子
            node.parent.lchild = None
        else:   #右孩子
            node.parent.rchild = None

    def __remove_node_21(self, node):
        # 狀況2.1:node只有一個左孩子
        if not node.parent: # 根節點
            self.root = node.lchild
            node.lchild.parent = None
        elif node == node.parent.lchild:
            node.parent.lchild = node.lchild
            node.lchild.parent = node.parent
        else:
            node.parent.rchild = node.lchild
            node.lchild.parent = node.parent

    def __remove_node_22(self, node):
        # 狀況2.2:node只有一個右孩子
        if not node.parent:
            self.root = node.rchild
        elif node == node.parent.lchild:
            node.parent.lchild = node.rchild
            node.rchild.parent = node.parent
        else:
            node.parent.rchild = node.rchild
            node.rchild.parent = node.parent


    def delete(self, val):
        if self.root:   # 不是空樹
            node = self.query_no_rec(val)
            if not node: # 不存在
                return False
            if not node.lchild and not node.rchild: #1. 葉子節點
                self.__remove_node_1(node)
            elif not node.rchild:       # 2.1 只有一個左孩子
                self.__remove_node_21(node)
            elif not node.lchild:       # 2.2 只有一個右孩子
                self.__remove_node_22(node)
            else:   # 3. 兩個孩子都有
                min_node = node.rchild
                while min_node.lchild:
                    min_node = min_node.lchild
                node.data = min_node.data
                # 刪除min_node
                if min_node.rchild:
                    self.__remove_node_22(min_node)
                else:
                    self.__remove_node_1(min_node)




#
#
# tree = BST([1,4,2,5,3,8,6,9,7])
# tree.in_order(tree.root)
# print("")
#
# tree.delete(4)
# tree.delete(1)
# tree.delete(8)
# tree.in_order(tree.root)
View Code

二叉搜索樹的效率

平均狀況下,二叉搜索樹進行搜索的時間複雜度爲O(nlogn)

最壞狀況下,二叉搜索樹可能很是偏斜(線性)

解決方案:

  • 隨機化插入
  • AVL樹

 

七、AVL樹

AVL樹是一顆自平衡的二叉搜索樹。

AVL樹具備一下性質:

  • 根的左右子樹的高度差的絕對值不能超過1
  • 根的左右子樹都是平衡二叉樹

AVL樹--插入

插入一個節點可能會破壞AVL樹的平衡,能夠經過旋轉操做來進行修正。

插入一個節點後,只有從插入節點到根節點的路徑上的節點的平衡可能被改變。咱們須要找出第一個破壞了平衡條件的節點,稱之爲K。k的左右子樹高度差的絕對值爲2

不平衡的出現可能會有4種狀況

一、左旋

不平衡是因爲對k的右孩子的右子樹插入致使的

二、右旋

不平衡是因爲對k的左孩子的左子樹插入致使的

三、右旋-左旋

不平衡是因爲對K的右孩子的左子樹插入致使的

四、左旋-右旋

AVL樹插入操做代碼實現:

from bst import BiTreeNode, BST

class AVLNode(BiTreeNode):
    def __init__(self, data):
        BiTreeNode.__init__(self, data)
        self.bf = 0

class AVLTree(BST):
    def __init__(self, li=None):
        BST.__init__(self, li)

    def rotate_left(self, p, c):
        s2 = c.lchild
        p.rchild = s2
        if s2:
            s2.parent = p

        c.lchild = p
        p.parent = c

        p.bf = 0
        c.bf = 0
        return c

    def rotate_right(self, p, c):
        s2 = c.rchild
        p.lchild = s2
        if s2:
            s2.parent = p

        c.rchild = p
        p.parent = c

        p.bf = 0
        c.bf = 0
        return c

    def rotate_right_left(self, p, c):
        g = c.lchild

        s3 = g.rchild
        c.lchild = s3
        if s3:
            s3.parent = c
        g.rchild = c
        c.parent = g

        s2 = g.lchild
        p.rchild = s2
        if s2:
            s2.parent = p
        g.lchild = p
        p.parent = g

        # 更新bf
        if g.bf > 0:
            p.bf = -1
            c.bf = 0
        elif g.bf < 0:
            p.bf = 0
            c.bf = 1
        else: # 插入的是g
            p.bf = 0
            c.bf = 0
        return g

    def rotate_left_right(self, p, c):
        g = c.rchild

        s2 = g.lchild
        c.rchild = s2
        if s2:
            s2.parent = c
        g.lchild = c
        c.parent = g

        s3 = g.rchild
        p.lchild = s3
        if s3:
            s3.parent = p
        g.rchild = p
        p.parent = g

        # 更新bf
        if g.bf < 0:
            p.bf = 1
            c.bf = 0
        elif g.bf > 0:
            p.bf = 0
            c.bf = -1
        else:
            p.bf = 0
            c.bf = 0
        return g

    def insert_no_rec(self, val):
        # 1、和BST同樣插入(AVL要一邊插入一邊控制balance factor)
        p = self.root
        if not p:  # 空樹
            self.root = AVLNode(val)
            return
        while True:
            if val < p.data:
                if p.lchild:
                    p = p.lchild
                else:  # 左孩子不存在
                    p.lchild = AVLNode(val)
                    p.lchild.parent = p
                    node = p.lchild  # node 存儲的就是插入的節點
                    break
            elif val > p.data:
                if p.rchild:
                    p = p.rchild
                else:
                    p.rchild = AVLNode(val)
                    p.rchild.parent = p
                    node = p.rchild
                    break
            else:  # val == p.data
                return

        # 2、更新balance factor
        while node.parent:      # node.parent 不空
            if node.parent.lchild == node:      # 傳遞是從左子樹來的, 左子樹更沉了
                # 更新node.parent的bf -= 1
                if node.parent.bf < 0:      # 原來node.parent.bf = -1, 更新後變成-2
                    # 作旋轉
                    # 看node那邊沉
                    g = node.parent.parent  # 爲了連接旋轉後的子樹
                    x = node.parent
                    if node.bf > 0:
                        n = self.rotate_left_right(node.parent, node)
                    else:
                        n = self.rotate_right(node.parent, node)
                    # 記得:把n和g連起來
                elif node.parent.bf > 0:    # 原來node.parent.bf = 1更新後等於0
                    node.parent.bf = 0
                    break
                else:   # 原來node.parent.bf = 0, 更新以後變成-1
                    node.parent.bf = -1
                    node = node.parent
                    continue

            else:   # 傳遞是從右子樹來的,右子樹更沉了
                # 更新node.parent.bf += 1
                if node.parent.bf > 0:  # 原來node.parent.bf =1< 更新後變成2
                    # 作旋轉
                    # 看node哪邊沉
                    g = node.parent.parent  # 爲了鏈接旋轉以後的子樹
                    x = node.parent     # 旋轉前的子樹的根
                    if node.bf < 0:     # node.bf = -1
                        n = self.rotate_right_left(node.parent, node)
                    else:
                        n = self.rotate_left(node.parent, node)
                    # 記得連起來
                elif node.parent.bf < 0:    # 原來node.parent.bf = -1, 更新以後變成0
                    node.parent.bf = 0
                    break
                else:   # 原來node.parent.bf = 0, 更新以後變成1
                    node.parent.bf = 1
                    node = node.parent
                    continue

            # 鏈接旋轉後的子樹:
            n.parent = g
            if g:   # g不是空
                if x == g.lchild:
                    g.lchild = n
                else:
                    g.rchild = n
                break
            else:
                self.root = n
                break
AVL樹插入操做
相關文章
相關標籤/搜索