算法_數據結構相關知識

1、什麼是數據結構?html

數據結構是指相互之間存在着一種或多種關係的數據元素的集合和該集合中數據元素之間的關係組成。
簡單來講,數據結構就是設計數據以何種方式組織並存儲在計算機中。
好比:列表、集合與字典等都是一種數據結構。

「程序=數據結構+算法」

2、數據結構的分類算法

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

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

下面就來講說線性結構,樹結構見連接,圖結構待續。。數據結構

3、線性結構app

(1)棧函數

一、定義:棧是一個數據集合,能夠理解爲只能在一端進行插入或者刪除操做的列表。spa

二、棧的特色:後進先出(last-in,first-out),簡稱LTFO表設計

三、棧的概念:3d

  • 棧頂:容許插入和刪除的這一端稱之爲棧頂
  • 棧底:另外一固定的一端稱爲棧底
  • 空棧:不含任何元素的棧稱爲空棧

四、棧的基本操做:指針

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

如圖:

五、棧的Python實現

不須要本身定義,使用列表結構便可。

  • 進棧函數:append
  • 出棧函數:pop
  • 查看棧頂元素:li[-1]
複製代碼
li = []
li.append(1)
li.append(2)
li.append(3)
print(li)
print(li.pop())
print(li.pop())
print(li.pop())
# print(li.pop())  #當棧空的時候就會報錯
# print(li[-1]) #查看棧頂元素
複製代碼

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

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

例如:

()()[]{}        匹配
([{()}])        匹配
[](        不匹配
[(])        不匹配

 

代碼以下:

複製代碼
# 方式一
def brace_match(s):
    '''括號匹配問題'''
    stack = []
    # {()}[]
    match = {')': '(', '}': '{', ']': '['}
    match2 = {'(': ')', "{": "}", "[": "]"}
    for ch in s:
        # print(i)
        if ch in {'(', '{', '['}:  # 若是左括號在裏面就把左括號添加進去,等待和右括號匹配
            stack.append(ch)
        elif len(stack) == 0:  # 若是再次進來括號的時候,這時候發現棧空了,說明缺乏了左括號了
            print('缺乏了%s' % match[ch])
            return False
        elif stack[-1] == match[ch]:  # 好比棧頂元素是(,ch=')'
            stack.pop()
        else:
            print('括號不匹配')
            return False

    if len(stack) > 0:  # 若是棧剩餘了,說明缺乏了右括號
        print('缺乏了%s' % match2[stack[-1]])
        return False
    return '匹配成功'

# 方式二
def check_kuohao(s):
    stack = []
    for char in s:
        if char in {'(', '[', '{'}:
            stack.append(char)
        elif char == ')':
            if len(stack) > 0 and stack[-1] == '(':
                stack.pop()
            else:
                return False
        elif char == ']':
            if len(stack) > 0 and stack[-1] == '[':
                stack.pop()
            else:
                return False
        elif char == '}':
            if len(stack) > 0 and stack[-1] == '{':
                stack.pop()
        else:
            return False
    if len(stack) == 0:
        return True
    else:
        return False

ret = brace_match('{()}]')
print(ret)

print(check_kuohao('{()}]'))
複製代碼

(2)隊列

一、介紹

  • 隊列是一個數據集合,僅容許在列表的一端進行插入,另外一端進行刪除,
  • 進行插入的一端稱爲隊尾(rear),插入動做稱之爲進隊或入隊
  • 進行刪除的一端稱之爲對頭(front),刪除動做稱爲出隊

雙向隊列:對列的兩端都容許進行進隊和出隊操做

二、隊列的實現

隊列可否簡單用列表實現?爲何?

  • 初步設想:列表+兩個下標指針
  • 建立一個列表和兩個變量,front變量指向隊首,rear變量指向隊尾。初始時,front和rear都爲0。
  • 進隊操做:元素寫到li[rear]的位置,rear自增1。
  • 出隊操做:返回li[front]的元素,front自減1。

 

三、隊列的實現原理-----環形對列

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

  • 實現方式:求餘數運算
  • 隊首指針前進1:front = (front + 1) % MaxSize
  • 隊尾指針前進1:rear = (rear + 1) % MaxSize
  • 隊空條件:rear == front
  • 隊滿條件:(rear + 1) % MaxSize == front

三、對列的內置模塊

使用方法:from collections import deque   #deque是支持雙向隊列的

  • 建立隊列:queue = deque(li)
  • 進隊:append
  • 出隊:popleft
  • 雙向隊列隊首進隊:appendleft
  • 雙向隊列隊尾進隊:pop
複製代碼
from collections import deque
queue = deque()#建立隊列
queue.append('first')
queue.append('second')
queue.append('third')
print(queue.popleft())
print(queue.popleft())
print(queue.popleft())#出隊,,先進先出
print([i for i in queue])  #查看隊列裏的元素

queue.appendleft('one')#雙向隊列隊首進隊
queue.appendleft('two')#雙向隊列隊首進隊
queue.appendleft('five')#雙向隊列隊首進隊
print(queue.pop())
print(queue.pop())#雙向隊列從隊尾出隊
print([i for i in queue])



#單向隊列
from queue import Queue
q = Queue()
q.put('a')
q.put('b')
q.put('c')
print(q.get())  #a
複製代碼

 

(3)單鏈表

鏈表中每個元素都是一個對象,每個對象都是一個節點,包含有數據域key和指向下一個節點的指針next。經過各個節點之間的互相鏈接,最終串聯成一個列表

一、節點定義:

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

二、創建鏈表

 頭插法

尾插法

 

三、鏈表的遍歷

四、鏈表節點的插入和刪除

複製代碼
# 插入:
p.next = curNode.next
curNode.next = p

#刪除:
p = curNode.next
curNode.next = p.next  #當前節點的下一個指向就指向他下一個的下一個
del p 
複製代碼

插入:

刪除:

< >(4)雙鏈表

雙鏈表中的每一個節點有兩個指針:一個指向後面節點、一個指向前面節點

一、節點定義:

class Node(object):
    def __init__(self,item):
        self.item = item  #數據
        self.next = None  #下一個指向 
        self.prior = None #上一個指向

 

二、雙鏈表節點的插入和刪除

複製代碼
#插入
p.next = curNode.next
curNode.next.prior = p 
p.prior = curNode
curNode.next = p

#刪除
p = curNode.next
curNode.next = p.next
p.next.prior = curNode
del p
複製代碼

 

(1) 

(2)

(3)

(4)

這四張圖片分別對應上面的四行代碼

(5)哈希表

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

一、簡單哈希函數

  • 除法哈希:h(k) = k mod m  #mod就是%      #除留餘數法
  • 乘法哈希:h(k) = floor(m(kA mod 1))   0<A<1  #floor是向下取整

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

 

二、哈希衝突

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

這種狀況叫作哈希衝突。

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

三、解決哈希衝突的辦法

  • a、開放尋址法
  • b、拉鍊發

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

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

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

 

四、哈希表在Python中的應用

  • a、字典與集合都是經過哈希表來實現的
  • b、 在Python中的字典:a = {'name': 'Alex', 'age': 18, 'gender': 'Man'},使用哈希表存儲字典,經過哈希函數將字典的鍵映射爲下標。

                 假設h(‘name’) = 3, h(‘age’) = 1, h(‘gender’) = 4,則哈希表存儲爲[None, 18, None, ’Alex’, ‘Man’]

  • c、在字典鍵值對數量很少的狀況下,幾乎不會發生哈希衝突,此時查找一個元素的時間複雜度爲O(1)。

 

參考or轉發

https://www.cnblogs.com/haiyan123/p/8407450.html

相關文章
相關標籤/搜索