1. 程式人生 > 其它 >Python學習18--常用的資料結構以及查詢方法實現

Python學習18--常用的資料結構以及查詢方法實現

技術標籤:Python

一、常用的資料結構

1、陣列

陣列在記憶體中是連續儲存,通過起始位置和偏移量來對其中每一個元素進行訪問;
優點:隨機訪問很好。資源使用少
缺點:插入或者刪除元素比較麻煩。
第一個元素:起始地址+0偏移量
第二個元素:起始位置+1
偏移量
第i個元素: 起始位置+(i-1)*偏移量

在這裡插入圖片描述
時間複雜度 :陣列的隨機訪問元素時間複雜度O(1):常數時間複雜度
線性儲存:每個元素都有一個前驅元素,一個後續元素

2、連結串列

連結串列是線性儲存的資料結構,跟陣列不同在於,連結串列不是連續的,連結串列中的每一個點被稱為【節點】,每個節點都包含兩個部分:資料域和指標域
其中資料域儲存的是元素,指標域儲存的是下一個節點的地址

連結串列分為:單向連結串列、雙向連結串列(有三個區域,中間的是資料域,前驅元素的地址,後續元素的地址)
在這裡插入圖片描述
優點:連結串列插入或者刪除元素效率高,只需要修改指標域即可
缺點:連結串列的隨機訪問性不好,資源佔用的多。
如果既要有隨機訪問性,又刪除和新增操作快-----在連結串列和陣列中選一個的話只能選陣列,理由如下:
1、節省空間
2、新增和刪除操作,連結串列本身也需要遍歷(訪問),找到對應的元素,所以可能也會浪費時間

3、堆疊(棧)

受限的線性表:只能在線性表的一端新增或者刪除元素,不能在中間新增或者刪除元素。
棧頂,棧底
出棧順序:無論是新增元素,刪除元素,都是從棧頂操作。
後進先出,棧頂元素先出 LIFO last in first out

應用場合: 函式呼叫,異常的傳播和丟擲

4、佇列

受限的線性表,只能在隊尾新增元素,只能在隊頭刪除元素,不能在中間新增或者刪除元素
隊頭(表頭),隊尾(表的最後一個元素)
出佇列的順序:先進先出,隊頭元素先出 FIFO first in first out
雙端佇列:同時實現佇列和堆疊的特性

5、樹

樹是由節點集和連線每對節點的有向邊集組成,結構有:根、父節點、子節點、葉子節點(沒有子節點)

二叉樹:任何一個節點的孩子數不超過兩個,分別稱為左子樹和右子樹

滿二叉樹:樹的深度m,2^m-1個節點,(除了葉子節點以外,其餘都有兩個孩子)

完全二叉樹:當所有節點的編號跟滿二叉樹一致,這種二叉樹是完全二叉樹

二叉樹的遍歷分為三種,都是針對根節點來說的
先序遍歷:先根、左、右
中序遍歷:左,根,右
後序遍歷:左,右,根

6、雜湊表

雜湊對映
數學上函式y=f(x) ---- y=x+1
將一組關鍵字對映到有限的地址集合上,這種就叫做雜湊散列表
關鍵字對映到相應地址的函式:雜湊函式
python中字典使用的是雜湊表儲存結構

二、演算法的衡量標準

時間複雜度:以最壞時間複雜度為準
常用的時間複雜度
O(1)< O(logn)<O(n)<O(nlogn)<O(n^2)

O(1)複雜度【注意沒有O(2)、O(3)】指:

x=1
y=2

O(logn)複雜度指:

while n!=0:
    print(n)
    n=n//2

O(n)複雜度指:

n=10
for i in range(n):
    print("x")

O(n^2)複雜度指:

for  i in range(n):
    # for j in range(n):
    for j in range(i):
        print("x")

空間複雜度:用空間為代價,換取時間

三、查詢演算法的實現

1、順序查詢

前到後,順序查詢跟關鍵字元素相符合的元素

def search(li,key):
    for index,i in enumerate(li):
        if i==key:
            return index
    return -1

li=[1,2,5,6,77,88]
print(search(li,6))

時間複雜度是O(n)

2.折半查詢

前提條件:列表中的元素必須是有序
選擇中間的元素進行比較,每次排除一半的元素

def findMiddle(key,li):
    startIndex = 0
    endIndex = len(li)-1

    while startIndex<= endIndex:
        middleIndex = (startIndex + endIndex) // 2
        if key == li[middleIndex]:
            return middleIndex
        elif key < li[middleIndex]:
            endIndex = middleIndex-1
        elif key>li[middleIndex]:
            startIndex = middleIndex+1
    return -1

時間複雜度: O(logn)

折半查詢是不是一定好於順序查詢?
折半查詢需要先進行排序,當重複呼叫查詢的方法的時候,適合折半查詢。進行排序之後,一勞永逸的進行查詢。