Python學習日誌之Python數據結構初識

Python數據結構初識:

一、Python數據結構概述

1.何爲數據結構

   在程序中,同樣的一個或幾個數據組織起來,可以有不同的組織方式,也就是不同的存儲方式,不同的組織方式就是不同的結構,我們把這些數據組織在一起的結構就叫做數據結構

例如:

   有一串字符串:"abc",我們將它重新組織一下,比如通過list()函數將"abc"變成["a","b","c"],那麼這個時候數據發生了重組,重組之後的結構就發生了變化,我們把["a","b","c"]這種結構叫做列表,也就是說列表是數據結構的一種類型之一。數據結構除了列表之外還有元組(),字典{"":"",}、隊列、棧、樹等。


2.數據結構實例

    Python中的數據結構有很多類型。其中,Python中系統自己定義的不需要我們自己去定義的數據結構叫做Python的內置數據結構,比如列表、元組等,而有一些數據組織方式,Python系統裏面沒有直接定義,需要我們自己去定義這些數據的組織方式,這些組織方式稱爲Python的擴展數據結構,比如棧、隊列等。


#實例:

#Python內置的數據結構有元組、列表、字典等。

#現在有三個物品,分別是"apple","orange","pear",需要把這三個物品存儲起來

#存儲方式1:這三個物品每個物品按順序分別存儲到一個櫃子裏,這些物品可以取出來,如下:可以修改

["apple","orange","pear"]


#存儲方式2:這三個物品每個物品按順序分別存儲到一個櫃子裏,但是物品不可以取出來,也不可以放到其他櫃子,如下,其實就是不可修改

("apple","orange","pear")


#存儲方式3:這三個物品不僅按順序存儲到一個櫃子裏,而且每個櫃子還有一個名詞

{"sam":"apple","jac":"orange","mating":"pear"}


3.數據結構和算法的關係

    在程序設計中,我們會發現數據結構經常和算法合在一起,這是爲什麼呢?其實,數據結構是數據的組織方式,就是存儲方式,也就是說,數據結構是靜態的。算法是指運算方法,通俗的說,就是運算思維,程序是動態的,需要將數據進行計算,運算方法有很多,不同的運算方法叫做不同的算法,所以我們可以這樣理解:數據結構是算法的基礎,但相同的數據結構運用不同的算法擁有不同的效率


二、Python常見數據結構-棧

1.何爲棧

    棧是一種數據結構,這種數據結構不同於系統自帶的內置數據結構,屬於擴展數據結構,需要自己定義

特點:棧相當於一端開口一端封閉的容器,數據A可以存儲在棧裏面,把數據A移動到裏面這個過程叫做進棧,也叫壓棧、入棧

    如果數據A到達棧頂後,同是佔了棧的一個位置,當再進入一個數據B的時候,也將到達棧頂,然後使A到棧頂的下一個位置,棧只能對棧頂的數據進行操作,此時就不能對A進行操作,可以將B出棧或刪除,等B出棧後,A變成棧頂的時候就可以對A進行操作


2.棧的圖示

   只能從開口進開口出,棧頂指向新數據的位置,棧底不變,用過棧頂指針的移動進行數據的進棧出棧。


3.Python中棧的實現

   棧是列表的擴展,只是棧只能從棧頂進行修改,不像列表可以從任意地方

#實例:

#棧的實現:

#棧是列表的擴展,只是棧只能從棧頂進行修改,不像列表可以從任意地方


 

class Stack():             #定義棧的類
     def __init__(st,size): #初始化函數,兩個形參,一個代表主體,一個代表容
量
         st.stack=[];       #聲明瞭棧
         st.size=size;      #聲明棧的容量
         st.top=-1;         #初始與棧底重合的棧頂
     def push(st,content):  #入棧定義
         if st.Full():
             print"Stack is Full"
         else:
            st.stack.append(content)  #入棧,數據進入,append增加內容,調用
append方法
            st.top=st.top+1           #棧頂指針加1
     def out(st):
         if st.Empty():
             print"Stack is Empty!"
         else:
             st.top=st.top-1
            
     def Full(st):          #判斷棧是否Full
         if st.top==st.size:
             return True    #棧滿
         else:
             return False
     def Empty(st):
         if st.top==-1:
             print"Stack is Empty!"


三、Python常見數據結構-隊列

1.何爲隊列

    隊列也是一種擴展的數據結構

特點:兩端開的開口容器,但是只能在一端進行刪除操作,不能進行插入操作,而另一端只能進行插入操作而不能進行刪除操作,進行插入的這端叫做隊尾,進行刪除操作的這端叫做隊首

    數據是隊尾進隊首出,類似於排隊

    隊首隊尾不是根據位置來區別的,是根據功能來區分的


2.隊列的圖示

    隊尾進隊首出

    進隊:qu.tail=qu.tail+1

    出隊:qu.head=qu.head+1


3.Python中隊列的實現

#隊列的實現
class Queue():                  #隊列類
    def __init__(qu,size):      #初始化信息,隊列主體qu,隊列容量size
        qu.queue=[];            #用列表聲明
        qu.size=size;           #傳遞進來的參數信息
        qu.head=-1;             #剛開始的隊首隊尾都在輸出方
        qu.tail=-1;
    def Empty(qu):              #先判斷是否爲空
        if qu.head==qu.tail:    #空的時候隊首隊尾指針參數
            return True
        else:
            return False
    def Full(qu):               #判斷隊列是否已滿
        if qu.tail-qu.head+1==qu.size:
            return True
        else:
            return False
    def enQueue(qu,content):    #進隊
        if qu.Full():
            print "Queue is Full!"
        else:
            qu.queue.append(content)
            qu.tail=qu.tail+1   #進隊只和隊尾相關,隊尾指針加1
    def outQueue(qu):           #出隊
        if qu.Empty():
            print "Queue is Empty!"
        else:
            qu.head=qu.head+1   #出隊指針只和隊首相關,隊首加1

            

四、Python常見數據結構-樹

1.何爲樹:

    樹是一種非線性的數據結構,樹具有非常高的層次性。利用樹來存儲數據,能夠是用公有元素進行存儲,能夠很大程度上節約空間。

定義:有且只有一個根節點,其次有N個不相交的子集,每個子集爲一顆子樹


2.樹的圖示:


3.什麼是二叉樹:

    二叉樹市一中特殊的樹,二叉樹要麼是空樹,要麼是左、右兩個不相交的子樹組成,二叉樹是有序樹,即使只有一個子樹,也需要區分該子樹是左子樹還是右子樹。二叉樹每個節點的度不可能大於2,可以取0,1,2。二叉樹的存儲方式有兩種,一種是順序方式,一種是鏈式存儲。

順序存儲採用一維數組的存儲方式

鏈式存儲中,採用表的存儲方式,通常分爲三部分:數據域,左孩子鏈域和右孩子鏈域


4.二叉樹的圖示:

有5種情況,加上空樹


5.Python中樹以及二叉樹的實現:通過列表表示

#1.樹的基本構造

#樹通過逗號,隔開

#樹是由列表構成的,實際上Tree2=[58,6,[5]],Tree3=[5]
Tree=[2,3,[58,6,[5]]]
print Tree[0]
print Tree[1]
print Tree[2]
Tree2=Tree[2]
print Tree2[0]
>>> 
2
3
[58, 6, [5]]
58#實現了樹的嵌套,子樹
>>>


#2.二叉樹的構造

'''

比如要構造一個二叉樹:

      7

  8       9

   23       36

57   58

可以這樣分析:

節點(左節點,右節點,當前節點數據)

根節點base=(-->8也就是jd2,-->9也就是jd3,base)

jd2=(no,-->23也就是jd4,8)

jd3=(no,-->36也就是jd5,9)

jd4=(-->57也就是jd6,-->58也就是jd7,23)

jd5=(no,no,36)

jd6=(no,no,57)

jd7=(no,no,58)

但是要注意,寫的時候倒過來寫,就是從右葉子開始寫,直到根節點

jd7=(no,no,58)

jd6=(no,no,57)

'''

class TRee():    #樹的初始化
    def __init__(self,leftjd=0,rightjd=0,data=0):
        self.leftjd=leftjd;
        self.rightjd=rightjd;
        self.data=data;
class Btree():  #二叉樹的初始化
    def __init__(self,base=0):
        self.base=base
    def empty(self):
        if self.base is 0:
            return True
        else:
            return False
    def qout(self,jd):
        """前序遍歷,NLR,根左右"""
        if jd==0:
            return   #沒有節點的話,原樣返回
        print jd.data  #先返回根節點的值
        self.qout(jd.leftjd)  #訪問左節點
        self.qout(jd.rightjd) #訪問右節點
    def mout(self,jd):
        """中序遍歷,LNR,左根右"""
        if jd==0:
            return
        self.mout(jd.leftjd)
        print jd.data
        self.mout(jd.rightjd)
    def hout(self,jd):
        """後序遍歷,LRN,左右根"""
        if jd==0:
            return
        self.hout(jd.leftjd)
        self.hout(jd.rightjd)
        print jd.data
>>> jd1=TRee(data=8)
>>> jd2=TRee(data=9)
>>> base=TRee(jd1,jd2,7)
>>> x=Btree(base)  #調用Btree
>>> x.qout (x.base) #前序遍歷NLR根左右
7
8
9
>>> x.mout (x.base) #中序遍歷LNR左根右
8
7
9
>>> x.hout (x.base) #後序遍歷LRN左右根
8
9
7
>>>


五、Python常見數據結構-鏈表

1.何爲鏈表

    鏈表也是一種數據結構,鏈表是一種非連續,非順序的存儲方式,鏈表由一系列節點組成,每個節點包括兩個部分,一部分是數據域,另一個部分是指向下一節點的指針域,鏈表可以分爲單向鏈表,單向循環鏈表,雙向鏈表,雙向循環鏈表。


單向鏈表:a可以指向b,但是b不能指向a

單向循環鏈表:表頭和表尾首尾相連,仍是單項

雙向鏈表:a可以指向b,b也可以指向a

雙向循環鏈表:首尾相連,可以順時針,也可以逆時針


2.鏈表的圖示

指針域:指向下一個節點的位置

節點之間是不相連的


3.Python中鏈表的實現

#鏈表的實現(單向鏈表)
class jd():   #節點類,存儲數據
    def __init__(self,data):  #初始化
        self.data=data
        self.next=None  #最初的時候不指向
    
class Linklist():  #鏈表類,實現鏈表作用
    def __init__(self,jd2):  #初始化
        self.head=jd2        #把jd2傳到表頭
        self.head.next=None  #下一個位置
        self.tail=self.head  #初始化表頭表尾重合
    def add(self,jd2):       #增加鏈表節點
        self.tail.next=jd2   #將節點2賦值到鏈表尾
        self.tail=self.tail.next
    def view(self):          #查看鏈表的所有情況
        jd2=self.head        #表頭
        linkstr=""           #節點的數據,轉化成字符串,然後不斷累加
        while jd2 is not None:  #節點2不爲空,開始
            if jd2.next is not None: #節點2下一個節點不爲空,開始遍歷
                linkstr=linkstr+str(jd2.data)+"-->"  #開始遍歷節點
            else:
                linkstr+=str(jd2.data)
            jd2=jd2.next
        print linkstr    #打印出鏈表linkstr
>>> jd1=jd(7)
>>> jd2=jd("hello")
>>> jd3=jd(8)
>>> x=Linklist(jd1)
>>> x.add (jd3)
>>> x.add (jd2)
>>> x.view ()
7-->8-->hello
>>>


六、Python常見數據結構-bitmap:通過數組表示

1.何爲bitmap

    同樣,bitmap也是一種數據結構。bit指的是位,map指的是圖,bitmap也叫是位圖。這種數據結構的存儲簡單來說就是把原來的數轉化成二進制來存儲,每個位佔一個存儲單元。我們對bitmap進行數據操作時,也就相當於操作一個位。bitmap的數據結構的優點是可以實現很好的排序


2.bitmap的圖示

最高位爲符號位,Python中一個數是32位,最右邊爲最低位,位圖上存在數就變成1,不存在就是0

00000000 00000000 00000000 00000101

2^2+2^0=5,上面是數字5的二進制形式,實際上bitmap和二進制數值是有差異的

def bitIndex(self, num): #位索引,算出數值所在單元

        return num % 31   

   

3.Python中bitmap的實現

(1).bitmap排序原理:

例如:請比較1,2,34的大小(出去符號位最高位在左邊)

數組1:可以存儲31個數,除去符號位,範圍1-31

數組2:可以存儲31個數,除去符號位,範圍32-62

1:存儲到數組1,2^0

2:存儲到數組1,2^1

34:存儲到數組2,34-32=2,再加1,就是數組2第三位

首先:數組2的大於數組1,從右往左依次增大

開始時bitmap爲0,當所對應的位置存在數據時,就開始映射到bitmap對應位置,位置


上的0變成1

#(2).bitmap的實現 
class Bitmap():
    def __init__(self, max): #最大的數
        self.size  = int((max+31 - 1) / 31) #計算所需要的數組個數
        self.array = [0 for i in range(self.size)]  #從數組中開始生成單元,
每個單元存儲的值都是0
        
    def bitIndex(self, num): #位索引,算出數值所在單元
        return num % 31      
 
    def set(self, num):      #置1
        elemIndex =num / 31  #判斷所在數組
        byteIndex = self.bitIndex(num)   #計算位索引
        elem= self.array[elemIndex]      #對應選擇的數組
        self.array[elemIndex] = elem |(1 << byteIndex)  #置1,向左移動的次數
    def test(self, i):
        elemIndex = i / 31   #判斷在第幾個數組
        byteIndex = self.bitIndex(i)
        if self.array[elemIndex] & (1 << byteIndex): #判斷是否在bitmap,不應
該超出範圍
            return True
        return False
 
if __name__ == '__main__':
    MAX = ord('z')  #設置最大數爲‘z’使用ord轉化成ansll
    suffle_array = [x for x in 'coledraw'] #將單詞拆分
    result       = []
    bitmap = Bitmap(MAX) #將MAX傳遞到Bitmap
    for c in suffle_array:  #從c開始調用到set
        bitmap.set(ord(c))
    for i in range(MAX + 1):  
        if bitmap.test(i):    #如果存在i中存在數值,進行依次調用到test
            result.append(chr(i))
 
    print '原始數組爲:    %s' % suffle_array #拆分後的數組
    print '排序後的數組爲: %s' % result
>>> =============================== RESTART ===============================
>>> 
>>> 
原始數組爲:    ['c', 'o', 'l', 'e', 'd', 'r', 'a', 'w']
排序後的數組爲: ['a', 'c', 'd', 'e', 'l', 'o', 'r', 'w']
>>>


七、Python常見數據結構-圖

1.何爲圖

    圖仍是一種數據結構,我們可以簡單的理解成一個關係網絡,該網絡中有N多結點,每個結點都存儲着一個數據,數據之間的關聯我們可以用線把關聯的結點連起來的方式進行表示。

    其中,有的數據關係是有方向的,比如數據A-->數據B,其關係只能從A到B,而不能從B到A,如果數據之間的關係是有方向,我們在圖裏面用帶箭頭弧線表示。有的數據關係是沒有方向的,A--B表示既可以從A關聯到B,也可以B關聯A,這種沒有方向的關係用線段表示。


2.圖的圖示

    不同的結點之間有的有直接聯繫,有的通過中間結點有間接聯繫  


3.Python中圖的實現

#圖的實現
chart={"A":["B","D"],"C":["E"],"D":["C","E"]}#圖通過字典表示
#"A":["B","D"]:A-->B,A-->D
#"C":["E"]:C-->E
#"D":["C","E"]:D-->C,D-->E
def path(chart,x,y,pathd=[]):
#chart:圖
#x:起始結點
#y:指向結點
#pathd=[]:走過的路徑
    pathd=pathd+[x]  #初始結點
    if x==y:
        return pathd  #返回pathd
    if not chart.has_key(x):  #判斷是否存在結點
        return None
    
    for jd in chart[x]:   #結點在chart所直接對應的結點
        if jd not in pathd:
            newjd=path(chart,jd,y,pathd) #初始結點變成jd,尋找路徑
            if newjd:
                return newjd  #找到新結點的時候返回值
>>> =============================== RESTART ===============================
>>> 
>>> path(chart,"A","E")
['A', 'D', 'C', 'E']
>>>

與之共勉,入門學習,需要持之以恆。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章