數據結構與算法

數據結構是以某種形式將數據組織在一塊兒的集合,它不只存儲數據,還支持訪問和處理數據的操做。node

數據的邏輯結構python

1.線性結構:數據元素之間存在一個對一個的關係。算法

2.樹形結構:結構中的數據元素存在一個對多個的關係。數據結構

3.圖形結構或網狀結構:結構中的數據元素存在多個對多個的關係。app

4.集合結構:結構中的數據元素之間除了同屬於一個集合關係外,無其餘數據關係。ide

 

數據類型,是一個值的集合和定義在此集合上的一組操做的總稱。函數

抽象數據類型,是指一個數學模型以及定義在此數據模型上的一組操做。spa

 

算法是爲求解一個問題須要遵循的、被清楚指定的簡單指令的集合。設計

一個算法必須知足五個重要特性:有窮性、肯定性、可行性、有輸入、有輸出。3d

設計算法要求:正確性、可讀性、健壯性、效率與低存儲量需求

 

時間複雜度與大O記法

「大O記法」:對於單調的整數函數f,若是存在一個整數函數g和實常數c>0,使得對於充分大的n總有f(n)<=c*g(n),就說函數g是f的一個漸近函數(忽略常數),記爲f(n)=O(g(n))。也就是說,在趨向無窮的極限意義下,函數f的增加速度受到函數g的約束,亦即函數f與函數g的特徵類似。

時間複雜度:假設存在函數g,使得算法A處理規模爲n的問題示例所用時間爲T(n)=O(g(n)),則稱O(g(n))爲算法A的漸近時間複雜度,簡稱時間複雜度,記爲T(n)

時間複雜度的幾條基本計算規則

  1. 基本操做,即只有常數項,認爲其時間複雜度爲O(1)
  2. 順序結構,時間複雜度按加法進行計算
  3. 循環結構,時間複雜度按乘法進行計算
  4. 分支結構,時間複雜度取最大值
  5. 判斷一個算法的效率時,每每只須要關注操做數量的最高次項,其它次要項和常數項能夠忽略
  6. 在沒有特殊說明時,咱們所分析的算法的時間複雜度都是指最壞時間複雜度

常見時間複雜度之間的關係

O(1) < O(logn) < O(n) < O(nlogn) < O(n2) <O(n2logn) < O(n3) < O(2n) < O(n!) < O(nn)

 Python list操做

python dict操做

 

python中的list與tuple兩種類型採用的順序表實現技術。list就是採用分離式技術實現的動態順序表,若將數據區更換爲更大的存儲空間,則能夠不在改變表對象的前提下對其數據區進行擴充,全部使用這個表的地方都沒必要修改 只要在程序的運行環境(計算機系統)還有空間存儲,這種表結構就不會由於滿了而致使操做沒法進行 這種技術實現的順序表稱爲動態順序表

 在Python的官方實現中,list實現採用了以下的策略:在創建空表(或者很小的表)時,系統分配一塊能容納8個元素的存儲區;在執行插入操做(insert或append)時,若是元素存儲區滿就換一塊4倍大的存儲區。但若是此時的表已經很大(目前的閥值爲50000),則改變策略,採用加一倍的方法。引入這種改變策略的方式,是爲了不出現過多空閒的存儲位置。

 鏈表(linked list)是由一組被稱爲結點的數據元素組成的數據結構,每一個結點都包含結點自己的信息和指向下一個結點的地址。因爲每一個結點都包含了能夠連接起來的地址信息,因此用一個變量就可以訪問整個結點序列。也就是說,結點包含兩部分信息:一部分用於存儲數據元素的值,稱爲信息域;另外一部分用於存儲下一個數據元素地址的指針,稱爲指針域。鏈表中的第一個結點的地址存儲在一個單獨的結點中,稱爲頭結點或首結點。鏈表中的最後一個結點沒有後繼元素,其指針域爲空

 

單鏈表的實現

class Node(object):
    """節點"""
    def __init__(self,elem):
        self.elem =elem
        self.next = None


class SingleLinkList(object):
    """單鏈表"""

    def __init__(self,node=None):
        self._head = node

    def is_empty(self):
        """判斷是否爲空"""
        return self._head == None

    def length(self):
        """長度"""
        cur = self._head
        count = 1
        while cur != None:
            count += 1
            cur = cur.next
        return count

    def travel(self):
        """遍歷鏈表"""
        cur = self._head
        while cur != None:
            print(cur.elem,end=',')
            cur = cur.next
        print()

    def add(self,item):
        """頭部添加"""
        node =Node(item)
        node.next = self._head
        self._head = Node

    def append(self,item):
        """尾部添加"""
        node = Node(item)
        if self.is_empty():
            self._head = node
        else:
            cur = self._head
            while cur.next != None:
                cur = cur.next
            cur.next = node

    def insert(self,pos,item):
        """指定位置添加"""
        if pos <= 0:
            self.add(item)
        elif pos > self.length()-1:
            self.append(item)
        else:
            pre = self._head
            count = 0
            while  count < (pos-1):
                count+=1
                pre = pre.next
            node = Node(item)
            node.next = pre.next
            pre.next = node

    def remove(self,item):
        """刪除元素"""
        cur = self._head
        pre = None
        while cur != None:
            if cur.elem == item:
                if cur == self._head:
                    self._head = cur.next

                else:
                    pre.next = cur.next
                break

            else:
                pre = cur
                cur = cur.next

    def search(self,item):
        """判斷元素是否在鏈表中"""
        cur = self._head
        while cur != None:
            if cur.elem == item:
                return True
            else:
                cur = cur.next
        return False

if __name__=="__main__":

    li = SingleLinkList()
    print(li.is_empty())
    print(li.length())
    li.append(1)
    print(li.is_empty())
    print(li.length())
    li.append(2)
    li.append(3)
    li.insert(2,100)
    li.travel()
    li.append(9)
    li.remove(2)
    li.travel()
    print(li.search(100))


結果:
True
1
False
2
1,2,100,3,
1,100,3,9,
True
View Code

 

操做 鏈表 順序表
訪問元素 O(n) O(1)
在頭部插入/刪除 O(1) O(n)
在尾部安插入/刪除 O(n) O(1)
在中間插入/刪除 O(n) O(n)

 

 

 

 

 

單向循環鏈表:單鏈表的一個變形是單向循環鏈表,鏈表中最後一個節點的next域再也不爲None,而是指向鏈表的頭結點。

class Node:
    """節點"""
    def __init__(self, item):
        self.item = item
        self.next = None

    def __str__(self):
        return str(self.item)


class SinCycLinkedList:
    """單向循環鏈表"""
    def __init__(self):
        self._head = None

    def is_empty(self):
        """判斷鏈表是否爲空"""
        return self._head is None

    def length(self):
        """鏈表長度"""
        if self.is_empty():
            return 0
        count = 1
        cur = self._head
        while cur.next != self._head:
            # print("cur", cur.item)
            count += 1
            cur = cur.next
        return count

    def travel(self):
        """遍歷"""
        if self.is_empty():
            return

        cur = self._head
        print(cur.item)
        while cur.next != self._head:
            cur = cur.next
            print(cur.item)

    def add(self, item):
        """在頭部添加一個節點"""
        node = Node(item)
        if self.is_empty():
            self._head = node
            node.next = self._head
        else:
            node.next = self._head
            cur = self._head
            while cur.next != self._head:
                cur = cur.next

            cur.next = node
            self._head = node

    def append(self, item):
        """在尾部添加一個節點"""
        node = Node(item)
        if self.is_empty():
            self._head = node
            node.next = self._head
        else:
            cur = self._head
            # print(type(cur), cur.item, cur.next)
            while cur.next != self._head:
                cur = cur.next

            # print(cur.item)
            cur.next = node
            node.next = self._head

    def insert(self, pos, item):
        """指定位置pos添加節點"""
        if pos <= 0:
            self.add(item)
        elif pos > (self.length() - 1):
            self.append(item)
        else:
            node = Node(item)
            cur = self._head
            cur_pos = 0
            while cur.next != self._head:
                if (pos - 1) == cur_pos:
                    node.next = cur.next
                    cur.next = node
                    break
                cur_pos += 1
                cur = cur.next

    def remove(self, item):
        """刪除一個節點"""
        if self.is_empty():
            return

        pre = self._head
        # 刪除首節點
        if pre.item == item:
            cur = pre
            while cur.next != self._head:
                cur = cur.next

            cur.next = pre.next     # 刪除首節點(跳過該節點)
            self._head = pre.next   # 從新指定首節點

        # 刪除其餘的節點
        else:
            cur = pre
            while cur.next != self._head:
                if cur.next.item == item:
                    cur.next = cur.next.next
                cur = cur.next

    def search(self, item):
        """查找節點是否存在"""
        if self.is_empty():
            return -1

        cur_pos = 0
        cur = self._head
        if cur.item == item:
            return cur_pos

        while cur.next != self._head:
            if cur.item == item:
                return cur_pos
            cur_pos += 1
            cur = cur.next

        if cur_pos == self.length() - 1:
            return -1


if __name__ == "__main__":
    ll = SinCycLinkedList()
    ll.add(1)       # 1
    ll.add(2)       # 2 1
    # ll.travel()
    ll.append(3)    # 2 1 3
    ll.insert(2, 4) # 2 1 4 3
    ll.insert(4, 5) # 2 1 4 3 5
    ll.insert(0, 6) # 6 2 1 4 3 5
    print("length:", ll.length())        # 6
    ll.travel()                           # 6 2 1 4 3 5
    print("search(3)", ll.search(3))     # 4
    print("search(7)", ll.search(7))     # -1
    print("search(6)", ll.search(6))    # 0
    print("remove(1)")
    ll.remove(1)
    print("length:", ll.length())       # 6 2 4 3 5
    print("remove(6)")
    ll.remove(6)
    ll.travel()

結果:
length: 6
6
2
1
4
3
5
search(3) 4
search(7) -1
search(6) 0
remove(1)
length: 5
remove(6)
2
4
3
5
View Code

 

雙向鏈表:一種更復雜的鏈表是 "雙向鏈表" 或 "雙面鏈表"。每一個節點有兩個連接:一個指向前一個節點,當次節點爲第一個節點時,指向空值;而另外一個指向下一個節點,當此節點爲最後一個節點時,指向空值。

class Node:
    """節點"""
    def __init__(self, item):
        self.item = item
        self.prev = None
        self.next = None


class DLinkList:
    """雙向鏈表"""
    def __init__(self):
        self._head = None

    def is_empty(self):
        """判斷鏈表是否爲空"""
        return self._head is None

    def length(self):
        """獲取鏈表長度"""
        if self.is_empty():
            return 0
        else:
            cur = self._head
            count = 1
            while cur.next is not None:
                count += 1
                cur = cur.next

            return count

    def travel(self):
        """遍歷鏈表"""
        print("↓↓" * 10)
        if self.is_empty():
            print("")

        else:
            cur = self._head
            print(cur.item)
            while cur.next is not None:
                cur = cur.next
                print(cur.item)
        print("↑↑" * 10)

    def add(self, item):
        """鏈表頭部添加節點"""
        node = Node(item)
        if self.is_empty():
            self._head = node
        else:
            cur = self._head

            node.next = cur
            cur.prev = node
            self._head = node

    def append(self, item):
        """鏈表尾部添加節點"""
        node = Node(item)
        if self.is_empty():
            self._head = node
        else:
            cur = self._head
            # 遍歷找到最後一個節點
            while cur.next is not None:
                cur = cur.next

            # 在尾節點添加新的節點
            cur.next = node
            node.prev = cur

    def insert(self, pos, item):
        """指定位置添加"""
        # 頭部添加
        if pos <= 0:
            self.add(item)

        # 尾部添加
        elif pos > (self.length() - 1):
            self.append(item)

        # 其餘位置添加
        else:
            node = Node(item)

            cur = self._head
            cur_pos = 0
            while cur.next is not None:
                if cur_pos == (pos - 1):
                    # 與下一個節點互相指向
                    node.next = cur.next
                    cur.next.prev = node
                    # 與上一個節點互相指向
                    cur.next = node
                    node.prev = cur
                cur_pos += 1
                cur = cur.next

    def remove(self, item):
        """刪除節點"""
        if self.is_empty():
            return
        else:
            cur = self._head
            # 刪除首節點
            if cur.item == item:
                self._head = cur.next
                cur.next.prev = None

            # 刪除其餘節點
            else:
                while cur.next is not None:
                    if cur.item == item:
                        # 刪除以前:1 ←→ [2] ←→ 3
                        # 刪除以後:1 ←→ 3
                        cur.prev.next = cur.next
                        cur.next.prev = cur.prev
                    cur = cur.next

                # 刪除尾節點
                if cur.item == item:
                    cur.prev.next = None


    def search(self, item):
        """查找節點是否存在"""
        if self.is_empty():
            return -1
        else:
            cur = self._head
            cur_pos = 0
            while cur.next is not None:
                if cur.item == item:
                    return cur_pos

                cur_pos += 1
                cur = cur.next

            if cur_pos == (self.length() - 1):
                return -1


if __name__ == "__main__":
    ll = DLinkList()
    ll.add(1)       # 1
    ll.add(2)       # 2 1
    ll.append(3)    # 2 1 3
    ll.insert(2, 4) # 2 1 4 3
    ll.insert(4, 5) # 2 1 4 3 5
    ll.insert(0, 6) # 6 2 1 4 3 5
    print("length:", ll.length())   # 6
    ll.travel()                 # 6 2 1 4 3 5
    print("search(3)", ll.search(3))
    print("search(4)", ll.search(4))
    print("search(10)", ll.search(10))
    ll.remove(1)
    print("length:", ll.length())
    ll.travel()
    print("刪除首節點 remove(6):")
    ll.remove(6)
    ll.travel()
    print("刪除尾節點 remove(5):")
    ll.remove(5)
    ll.travel()
結果:
length: 6
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
6
2
1
4
3
5
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
search(3) 4
search(4) 3
search(10) -1
length: 5
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
6
2
4
3
5
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
刪除首節點 remove(6):
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
2
4
3
5
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
刪除尾節點 remove(5):
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
2
4
3
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
View Code

 

數據結構只容許在一端進行操做,按照後進先出(LIFO,Last In First Out)。

棧結構的實現

# Author:song
class Stack(object):
    """"""
    def __init__(self):
        self._items = []

    def is_empty(self):
        """判斷是否爲空"""
        return self._items == []
    def push(self,item):
        """添加新元素到棧頂"""
        self._items.append(item)

    def pop(self):
        """彈出棧頂元素"""
        self._items.pop()

    def peek(self):
        """返回棧頂元素"""
        if self._items:
            return self._items[-1]
        else:
            return None
        pass
    def size(self):
        pass

if __name__=="__main__":
    s=Stack()
    print(s.is_empty())
View Code

 

隊列(queue)是隻容許在一端進行插入操做,而在另外一端進行刪除操做的線性表。一種先進先出(FIFO,First In First Out)的線性表

隊列的實現

class Queue:
    """隊列"""
    def __init__(self):
        self.items = []

    def is_empty(self):
        return self.items == []

    def enqueue(self, item):
        """添加元素"""
        self.items.insert(0, item)

    def dequeue(self):
        """從隊列頭部刪除一個元素"""
        return self.items.pop()

    def size(self):
        return len(self.items)


if __name__ == "__main__":
    q = Queue()
    q.enqueue("hello")
    q.enqueue("world")
    q.enqueue("queue")
    print(q.size())
    print(q.dequeue())      # hello
    print(q.dequeue())      # world
    print(q.dequeue())      # queue
View Code

 

雙端隊列,是一種具備隊列和棧的性質的數據結構。

class Deque:
    """雙端隊列"""
    def __init__(self):
        self.items = []

    def add_front(self, item):
        """從隊頭加入一個元素"""
        self.items.insert(0, item)

    def add_rear(self, item):
        """從隊尾加入一個元素"""
        self.items.append(item)

    def remove_front(self):
        """從隊頭刪除一個元素"""
        return self.items.pop(0)

    def remove_rear(self):
        """從隊尾刪除一個元素"""
        return self.items.pop()

    def is_empty(self):
        """是否爲空"""
        return self.items == []

    def size(self):
        """隊列長度"""
        return len(self.items)


if __name__ == "__main__":
    deque = Deque()
    deque.add_front(1)
    deque.add_front(2)
    deque.add_rear(3)
    deque.add_rear(4)
    print(deque.size())             # 4
    print(deque.remove_front())     # 2
    print(deque.remove_front())     # 1
    print(deque.remove_rear())      # 4
    print(deque.remove_rear())      # 3
View Code
相關文章
相關標籤/搜索