數(shù)據(jù)結(jié)構(gòu)與算法Python版(ing)

可以看這個(gè)特別好的:《數(shù)據(jù)結(jié)構(gòu)與算法基礎(chǔ)》教學(xué)視頻目錄

1.單向鏈表


單鏈表節(jié)點(diǎn)一個(gè)類隙畜,單鏈表一個(gè)類闲孤,單鏈表這個(gè)類中的元素都是節(jié)點(diǎn)類的。
單鏈表的操作:

  • is_empty() 鏈表是否為空
    取cur指向鏈表的首節(jié)點(diǎn)摹菠,判斷是不是None

  • length() 鏈表長(zhǎng)度
    取cur指向鏈表的首節(jié)點(diǎn)眼耀,設(shè)置count用來(lái)計(jì)數(shù)宽气,當(dāng)前指向若不為None肠缨,則計(jì)數(shù)+1逆趋,移動(dòng)cur指向下一個(gè)節(jié)點(diǎn)。

  • travel() 遍歷整個(gè)鏈表
    思路同鏈表長(zhǎng)度晒奕,把計(jì)數(shù)的部分換成print

  • first_add(item) 鏈表頭部添加元素



    新添加的元素需要定義成節(jié)點(diǎn)類的一個(gè)實(shí)例闻书。新添加的元素就是頭節(jié)點(diǎn),新添加節(jié)點(diǎn)的下一個(gè)指向原鏈表的頭節(jié)點(diǎn)脑慧。把鏈表的頭節(jié)點(diǎn)指向新添加的節(jié)點(diǎn)魄眉。

  • last_add(item) 鏈表尾部添加元素
    新添加的元素需要定義成節(jié)點(diǎn)類的一個(gè)實(shí)例。
    判斷當(dāng)前鏈表是不是為空闷袒,如果是空坑律,那這個(gè)鏈表的頭節(jié)點(diǎn)指向新添加的節(jié)點(diǎn)。
    如果不是空囊骤,那就將cur指向頭節(jié)點(diǎn)脾歇,按照travel()的思路遍歷這個(gè)鏈表,一直走到最后一個(gè)節(jié)點(diǎn)淘捡,將最后一個(gè)節(jié)點(diǎn)的下一個(gè)元素設(shè)置為新添加的這個(gè)節(jié)點(diǎn)。注意判斷是否最后一個(gè)節(jié)點(diǎn)的條件池摧。

  • insert(pos, item) 指定位置添加元素



    新添加的元素需要定義成節(jié)點(diǎn)類的一個(gè)實(shí)例焦除。
    判斷pos的值,如果pos<=0作彤,則相當(dāng)于在首部插入膘魄,調(diào)用首部插入的方法。
    如果pos的值>鏈表長(zhǎng)度-1(注意這里pos的值是從0開(kāi)始的)竭讳,則相當(dāng)于尾部插入创葡,調(diào)用尾部插入的方法。
    否則:定義pre指向當(dāng)前鏈表的頭節(jié)點(diǎn)绢慢,用一個(gè)count計(jì)算當(dāng)前指向的索引值灿渴,移動(dòng)cur直到走到pos-1的位置,將新節(jié)點(diǎn)的下一個(gè)元素指向原鏈表這個(gè)位置的下一個(gè)元素胰舆,原鏈表的下一個(gè)位置指向新節(jié)點(diǎn)骚露。見(jiàn)下圖


  • remove(item) 刪除節(jié)點(diǎn)



    定義兩個(gè)指針,pre一開(kāi)始是None缚窿,cur 指向原鏈表的頭節(jié)點(diǎn)棘幸。如果刪除的是頭節(jié)點(diǎn),那么把鏈表的頭節(jié)點(diǎn)指向原鏈表頭節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)倦零。如果不是頭節(jié)點(diǎn)误续,就將pre指向當(dāng)前cur的節(jié)點(diǎn)吨悍,cur的指向一個(gè)一個(gè)的往后挪,(這樣就相當(dāng)于pre在后蹋嵌,cur在前)直到cur指向的值就是我們要?jiǎng)h除的值育瓜,把pre的下一個(gè)節(jié)點(diǎn)指向cur的下一個(gè)節(jié)點(diǎn)。

  • search(item) 查找節(jié)點(diǎn)是否存在
    思路同travel()


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



class singleLinkList(object):
    def __init__(self):
        # 頭節(jié)點(diǎn)
        self._head = None
    def is_empty(self):
        return self._head == None

    def length(self):
        # 首先要指向頭節(jié)點(diǎn)
        cur = self._head
        count = 0
        while cur is not None:
            count = count+1
            cur = cur._next
        return count

    def travel(self):
        if self.is_empty():
            return
        # 首先要指向頭節(jié)點(diǎn)
        cur = self._head
        while cur != None:
            print(cur.item)
            cur = cur._next
        print("")
    def first_add(self,elem):
        # 把新添加的數(shù)定義到Node類里欣尼,這樣它就會(huì)有item和_next兩個(gè)屬性
        p = Node(elem)
        p._next = self._head
        # 把鏈表的頭節(jié)點(diǎn)指向新添加的節(jié)點(diǎn)
        self._head = p


    def last_add(self,elem):
        cur = self._head
        p = Node(elem)
        # 首先判斷這個(gè)鏈表是不是空的
        if self.is_empty():
            self._head = p
        else:
            cur = self._head
            while cur._next != None:
                cur = cur._next
            cur._next = p
    def insert(self,index,elem):
        # 如果插入的地方在第一個(gè)位置之前爆雹,直接調(diào)用在首部插入的方法
        if index<=0 :
            self.first_add(elem)
        # 如果插入的地方在最后一個(gè)位置之后,直接調(diào)用在尾部插入的方法
        elif index>(self.length()-1):
            self.last_add(elem)
        else:
            p = Node(elem)
            count = 0
            pre = self._head
            while count<(index-1):
                pre = pre._next
                count = count+1
            p._next = pre._next
            pre._next = p

    def remove(self,elem):
        cur = self._head
        pre = None
        while cur is not None:
            if cur.item == elem:
                #  如果第一個(gè)就是要?jiǎng)h除的節(jié)點(diǎn)
                if not pre:
                    self._head = cur._next
                else:
                    pre._next = cur._next
                break
            else:
                # 將刪除位置前一個(gè)節(jié)點(diǎn)的next指向刪除位置的后一個(gè)節(jié)點(diǎn)
                pre = cur
                cur = cur._next

    def search(self,elem):
        cur = self._head
        index = 0
        while cur is not None:
            if cur.item == elem:
                return index
            else:
                cur = cur._next
                index = index+1
        return index
if __name__ == "__main__":
    ll = singleLinkList()
    print("-------創(chuàng)建鏈表愕鼓,首部加1钙态,首部加2---------")
    ll.first_add(1)
    # print(ll.travel())
    ll.first_add(2)
    ll.travel()

    print("-------尾部添加3---------")
    ll.last_add(3)
    ll.travel()

    print("-------在索引為2的位置添加4---------")
    ll.insert(2, 4)
    print("length:",ll.length())
    ll.travel()

    print("-------查找鏈表中某一個(gè)數(shù)的索引---------")
    index = ll.search(2)
    print(index)

    print("-------刪除鏈表中某一個(gè)數(shù)---------")
    ll.remove(3)
    # print "length:",ll.length()
    ll.travel()

2.循環(huán)單鏈表

  • 首部添加元素



    首先判斷這個(gè)鏈表是不是空,如果是空菇晃,把頭指針指向新添加的這個(gè)p節(jié)點(diǎn)册倒,并且p節(jié)點(diǎn)的下一節(jié)點(diǎn)指向頭節(jié)點(diǎn)。(因?yàn)槭茄h(huán)的)
    如果不是空磺送,那么先把p節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)指向頭節(jié)點(diǎn)驻子,然后往后走,找到最后一個(gè)節(jié)點(diǎn)估灿,把原鏈表的最后一個(gè)節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)指向新加入的p節(jié)點(diǎn)崇呵,并且把頭指針指向這個(gè)p節(jié)點(diǎn)(因?yàn)槭鞘撞考尤耄?/p>

  • 尾部添加元素
    首先判斷原鏈表是不是空的,如果是空的馅袁,就按照上面的域慷,把頭指針(self._head)指向新添加的這個(gè)p節(jié)點(diǎn),并且p節(jié)點(diǎn)的下一節(jié)點(diǎn)指向頭節(jié)點(diǎn)汗销。
    如果不是空犹褒,就找到原鏈表的最后一個(gè)節(jié)點(diǎn),將最后一個(gè)節(jié)點(diǎn)的下一節(jié)點(diǎn)指向p節(jié)點(diǎn)弛针,然后p節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)指向頭節(jié)點(diǎn)叠骑,頭指針(self._head)沒(méi)變。
  • remove方法還需要好好看看削茁。

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



class circularLinkList(object):
    def __init__(self):
        # 頭節(jié)點(diǎn)
        self._head = None
    def is_empty(self):
        return self._head == None

    def length(self):
        # 首先要指向頭節(jié)點(diǎn)
        cur = self._head
        count = 0
        while cur is not None:
            count = count+1
            cur = cur._next
        return count


    def travel(self):
        if self.is_empty():
            return
        # 首先要指向頭節(jié)點(diǎn)
        cur = self._head

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


    def first_add(self,elem):
        # 把新添加的數(shù)定義到Node類里宙枷,這樣它就會(huì)有item和_next兩個(gè)屬性
        p = Node(elem)
        if self.is_empty():
            self._head = p
            p._next = self._head
        else:
            # 首先將新加入的這個(gè)節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)指向首節(jié)點(diǎn)
            p._next = self._head
            # 然后將原鏈表的尾節(jié)點(diǎn)指向這個(gè)新加入的節(jié)點(diǎn)
            cur = self._head
            while cur._next != self._head:
                cur = cur._next
            cur._next = p
            self._head = p


    def last_add(self,elem):

        p = Node(elem)
        # 首先判斷這個(gè)鏈表是不是空的
        if self.is_empty():
            self._head = p
            p._next = self._head
        else:
            # 直接走到最后的節(jié)點(diǎn)
            cur = self._head
            while cur._next != self._head:
                cur = cur._next
            cur._next = p
            p._next = self._head



    def insert(self,index,elem):
        # 如果插入的地方在第一個(gè)位置之前,直接調(diào)用在首部插入的方法
        if index<=0 :
            self.first_add(elem)
        # 如果插入的地方在最后一個(gè)位置之后茧跋,直接調(diào)用在尾部插入的方法
        elif index>(self.length()-1):
            self.last_add(elem)
        else:
            p = Node(elem)
            count = 0
            pre = self._head
            while count<(index-1):
                pre = pre._next
                count = count+1
            p._next = pre._next
            pre._next = p

    def remove(self,elem):
        # 如果原鏈表為空
        if self.is_empty():
            return

        cur = self._head
        pre = None

        # 如果鏈表的第一個(gè)元素就是要?jiǎng)h除的元素
        if cur.item == elem:
            # 如果鏈表多于一個(gè)節(jié)點(diǎn)朦拖,就找到最后一個(gè)節(jié)點(diǎn)
            if cur._next != self._head:
                while cur._next != self._head:
                    cur = cur._next
                cur._next = self._head._next
                self._head = self._head._next
            else:
                # 如果鏈表只有一個(gè)元素,就直接置空
                self._head = None
        else:
            pre = self._head
            while cur._next != self._head:
                # 如果找到了要找的元素
                if cur.item == elem:
                    pre._next = cur._next
                    return
                else:
                    pre = cur
                    cur = cur._next
            # cur指向了尾節(jié)點(diǎn)
            if cur.item == elem:
                pre._next = self._head



    def search(self,elem):
        if self.is_empty():
            return False
        cur = self._head
        index = 0
        while cur._next != self._head:
            if cur.item == elem:
                return index
            else:
                cur = cur._next
                index = index+1
        if cur.item == elem:
            return index
        else:
            return False

if __name__ == "__main__":
    ll = circularLinkList()
    # print(ll.length())
    ll.travel()
    print("--------首部添加----------")
    ll.first_add(2)
    ll.first_add(1)
    ll.first_add(99)
    ll.travel()
    print("--------尾部添加----------")
    ll.last_add(6)
    ll.travel()
    print("--------尾部添加----------")
    ll.last_add(5)
    ll.travel()
    print("--------移除元素----------")
    # ll.remove(5)
    # ll.travel()
    print("--------查找元素----------")
    print(ll.search(6))
   

3.棧
棧是一種特殊的線性表厌衔,僅能在線性表的一端操作璧帝,棧頂允許操作,棧底不允許操作富寿。
棧的特性:后進(jìn)先出

class Stack(object):
    def __init__(self):
        self.items = []
    def is_empty(self):
        # 判斷棧是否為空
        return self.items == []
    def push(self,elem):
        # 添加元素到棧
        self.items.append(elem)
    def pop(self):
        # 彈出元素
        return self.items.pop()
    def peek(self):
        # 返回棧頂?shù)脑?        return self.items[len(self.items)-1]
    def size(self):
        return len(self.items)
    def travel(self):
        for i in range(self.size()):
            print(self.items[i],end=" ")
if __name__ == '__main__':
    stack = Stack()
    print(stack.travel())
    print("======判斷棧是否為空==========")
    print(stack.is_empty())
    print("======棧頂加入元素==========")
    stack.push(2)
    stack.push(3)
    stack.push(12)
    stack.push(4)
    print(stack.travel())
    print("棧的長(zhǎng)度為:", stack.size())
    print("======判斷棧是否為空==========")
    print(stack.is_empty())
    print("======彈出棧頂元素==========")
    print(stack.pop())
    print("======返回棧頂元素==========")
    print(stack.peek())
    print("棧的長(zhǎng)度為:",stack.size())

4.隊(duì)列
隊(duì)列是一種特殊的線性表睬隶,特殊之處在于它只允許在表的前端(front)進(jìn)行刪除操作锣夹,而在表的后端(rear)進(jìn)行插入操作。
特點(diǎn):先進(jìn)先出


image.png
class Queue(object):
    def __init__(self):
        self.items =[]
    def is_empty(self):
        return self.items == []
    def enqueue(self,elem):
        # 隊(duì)列添加元素
        self.items.insert(0,elem)
    def dequeue(self):
        # 從隊(duì)列頭部刪除一個(gè)元素
        return self.items.pop()
    def size(self):
        return len(self.items)
if __name__ == '__main__':
    queue = Queue()
    print("======判斷隊(duì)列是否為空==========")
    print(queue.is_empty())
    print("======隊(duì)列加入元素==========")
    queue.enqueue(2)
    queue.enqueue("hello")
    queue.enqueue("end")

    print("隊(duì)列的長(zhǎng)度為:", queue.size())
    print("======判斷隊(duì)列是否為空==========")
    print(queue.is_empty())
    print("======返回隊(duì)列頭部元素==========")
    print(queue.dequeue())

    print("隊(duì)列的長(zhǎng)度為:",queue.size())

雙端隊(duì)列
特點(diǎn):雙端隊(duì)列可以在隊(duì)列任意一端入隊(duì)和出隊(duì)。

class DoubleQueue(object):
    """
    Deque() 創(chuàng)建一個(gè)空的雙端隊(duì)列
    add_front(item) 從隊(duì)頭加入一個(gè)item元素
    add_rear(item) 從隊(duì)尾加入一個(gè)item元素
    remove_front() 從隊(duì)頭刪除一個(gè)item元素
    remove_rear() 從隊(duì)尾刪除一個(gè)item元素
    is_empty() 判斷雙端隊(duì)列是否為空
    size() 返回隊(duì)列的大小
    """
    def __init__(self):
        self.items = []
    def is_empty(self):
        return self.items == []
    def add_front(self,elem):
        # 從隊(duì)頭加入一個(gè)元素
        self.items.insert(0,elem)
    def add_rear(self,elem):
        # 隊(duì)尾加入一個(gè)元素
        self.items.append(elem)
    def remove_front(self):
        # 隊(duì)頭刪除一個(gè)元素
        return self.items.pop(0)
    def remove_rear(self):
        # 隊(duì)尾刪除一個(gè)元素
        return self.items.pop()
    def size(self):
        return len(self.items)
    def travel(self):
        for i in range(self.size()):
            print(self.items[i],end=" ")
if __name__ == '__main__':
    deque = DoubleQueue()
    print("======判斷雙端隊(duì)列是否為空==========")
    print(deque.is_empty())
    deque.add_front(1)
    deque.add_front(2)
    deque.add_rear(3)
    deque.add_rear(4)
    print("======雙端隊(duì)列的值為:==========")
    deque.travel()
    print("雙端隊(duì)列的長(zhǎng)度為:",deque.size())
    print("======隊(duì)頭刪除的元素==========")
    print(deque.remove_front())
    print("======隊(duì)尾刪除的元素==========")
    print(deque.remove_rear())
    print("雙端隊(duì)列的長(zhǎng)度為:", deque.size())

4.樹(shù)
二叉樹(shù)
對(duì)于任意一棵二叉樹(shù),如果其葉結(jié)點(diǎn)數(shù)為N0咧虎,而度數(shù)為2的結(jié)點(diǎn)總數(shù)為N2骚灸,則N0=N2+1;
證明需要知道:二叉樹(shù)(非空)的結(jié)點(diǎn)數(shù)等于邊數(shù)+1(可以理解為淑趾,除了根節(jié)點(diǎn),每一個(gè)節(jié)點(diǎn)對(duì)應(yīng)一條邊),可以設(shè)度數(shù)為0的節(jié)點(diǎn)為N0,度數(shù)為1的節(jié)點(diǎn)N1戳气,度數(shù)為2的節(jié)點(diǎn)N2,有N0+N1+N2(節(jié)點(diǎn)數(shù))= 1+N1+2N2(邊數(shù))巧鸭,度數(shù)為1的節(jié)點(diǎn)對(duì)對(duì)應(yīng)一個(gè)邊瓶您,度數(shù)為2的節(jié)點(diǎn)對(duì)應(yīng)兩個(gè)邊。

  • 滿二叉樹(shù):一棵深度為k且有2的k次方減1個(gè)結(jié)點(diǎn)的二叉樹(shù)是滿二叉樹(shù)纲仍。除葉子結(jié)點(diǎn)外的所有結(jié)點(diǎn)均有兩個(gè)子結(jié)點(diǎn)呀袱。節(jié)點(diǎn)數(shù)達(dá)到最大值。所有葉子結(jié)點(diǎn)必須在同一層上郑叠。


  • 完全二叉樹(shù):若設(shè)二叉樹(shù)的深度為h夜赵,除第 h 層外,其它各層 (1~h-1) 的結(jié)點(diǎn)數(shù)都達(dá)到最大個(gè)數(shù)乡革,第 h 層所有的結(jié)點(diǎn)都連續(xù)集中在最左邊油吭,這就是完全二叉樹(shù)。



    二者的關(guān)系:滿二叉樹(shù)肯定是完全二叉樹(shù)署拟,完全二叉樹(shù)不一定是滿二叉樹(shù)。

  • 平衡二叉樹(shù)(AVL樹(shù)):當(dāng)且僅當(dāng)任何節(jié)點(diǎn)的兩棵子樹(shù)的高度差不大于1的二叉樹(shù)歌豺;
  • 排序二叉樹(shù)(二叉查找樹(shù)(英語(yǔ):Binary Search Tree)推穷,也稱二叉搜索樹(shù)、有序二叉樹(shù))类咧;

樹(shù)的前序遍歷:中左右
中序遍歷:左中右
后續(xù)遍歷:左右中

5. 圖 G=(V,E)

相關(guān)概念
圖的組成:頂點(diǎn)V和邊E
分類:有向圖和無(wú)向圖
頂點(diǎn)的度:對(duì)于無(wú)向圖來(lái)說(shuō)馒铃,一個(gè)頂點(diǎn)的度就是連接該頂點(diǎn)的邊的數(shù)量,記做D(V)痕惋;對(duì)于有向圖來(lái)說(shuō)区宇,分為入度ID(V)(以該頂點(diǎn)為端點(diǎn)的入邊數(shù)量)和出度OD(V)(以該頂點(diǎn)為端點(diǎn)的出邊數(shù)量),D(V)=ID(V)+OD(V)
鄰接頂點(diǎn):對(duì)于無(wú)向圖來(lái)說(shuō)值戳,就是一條邊的兩個(gè)頂點(diǎn)议谷;對(duì)于有向圖來(lái)說(shuō),兩個(gè)頂點(diǎn)分別稱為起始頂點(diǎn)(入邊鄰接頂點(diǎn))和結(jié)束頂點(diǎn)(出邊鄰接頂點(diǎn))
無(wú)向完全圖:M個(gè)頂點(diǎn)的無(wú)向完全圖總邊數(shù)為M(M-1)/2
有向完全圖:N個(gè)頂點(diǎn)的有向完全圖堕虹,總邊數(shù)為N(N-1)
有向無(wú)環(huán)圖(DAG圖):一個(gè)有向圖從一個(gè)頂點(diǎn)出發(fā)經(jīng)過(guò)若干條邊無(wú)法回到該頂點(diǎn)卧晓。
網(wǎng)(即有權(quán)圖)

圖的存儲(chǔ)結(jié)構(gòu)
圖的存儲(chǔ)結(jié)構(gòu):鄰接矩陣表示法芬首、鄰接表表示法
1??鄰接矩陣表示法:就是用兩個(gè)數(shù)組表示圖。缺點(diǎn)是n個(gè)頂點(diǎn)的圖需要n*n個(gè)存儲(chǔ)空間逼裆,當(dāng)圖為稀疏圖時(shí)會(huì)造成空間浪費(fèi)郁稍。
頂點(diǎn)表記錄頂點(diǎn)信息,鄰接矩陣表示頂點(diǎn)之間的關(guān)系胜宇。
有向圖鄰接矩陣中第i行表示以結(jié)點(diǎn)vi為尾的灰(即出度邊[發(fā)出的弧]),第j列表示的是以結(jié)點(diǎn)vj為頭的煌┯洹(即入度邊)财破,頂點(diǎn)的出度=第i行元素之和,頂點(diǎn)的入度=第j列元素之和

2??鄰接表表示法:(多重鏈表鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu))


頭結(jié)點(diǎn):一維數(shù)組仅财,其中有兩個(gè)元素狈究,第一個(gè)元素是頂點(diǎn)的數(shù)據(jù)元素本身,第二個(gè)元素是指針盏求,指向邊結(jié)點(diǎn)的地址抖锥。
表結(jié)點(diǎn):第一個(gè)元素表示鄰接的頂點(diǎn)是頂點(diǎn)表中的哪個(gè)元素,第二個(gè)指針指向下一個(gè)邊碎罚。
對(duì)于一個(gè)頂點(diǎn)來(lái)說(shuō)磅废,有幾個(gè)邊就記錄幾個(gè)邊結(jié)點(diǎn)
如果是網(wǎng),可以在表結(jié)點(diǎn)中增加一個(gè)域表示權(quán)值荆烈。

特點(diǎn):
鄰接表不唯一拯勉;若無(wú)向圖中有n個(gè)頂點(diǎn)e條邊,則鄰接表需要n個(gè)頭結(jié)點(diǎn)和2e個(gè)表結(jié)點(diǎn)憔购,適合存儲(chǔ)稀疏圖宫峦;有向圖中有n個(gè)頂點(diǎn)e條邊,則鄰接表需要n個(gè)頭結(jié)點(diǎn)和e個(gè)表結(jié)點(diǎn)
怎么看度玫鸟?有幾個(gè)表結(jié)點(diǎn)就是有幾個(gè)度导绷。

3.排序
冒泡排序(O(n^2))
思路:比較前后兩個(gè)數(shù)的大小,從前到后比較到最后屎飘,這樣第一次冒泡完最后一個(gè)數(shù)是整個(gè)里面最大的數(shù)妥曲,然后進(jìn)行第二次冒泡...假設(shè)我們要排序的有m個(gè)數(shù),那么就需要m-1次冒泡钦购。

def BubbleSort(myList):
    length = len(myList)
    for i in range(length-1):
        #注意這個(gè)地方檐盟,因?yàn)檫€有一個(gè)j+1,所以j的取值是length-i-1
        for j in range(length-i-1):
            if myList[j]>myList[j+1]:
                myList[j],myList[j+1] = myList[j+1],myList[j]
        print(myList)
BubbleSort([49,38,65,97,76,13,27])

選擇排序(O(n^2))
思路:首先在未排序序列中找到最小(大)元素押桃,存放到排序序列的起始位置葵萎,然后,再?gòu)氖S辔磁判蛟刂欣^續(xù)尋找最小(大)元素陌宿,然后放到已排序序列的末尾锡足。以此類推,直到所有元素均排序完畢壳坪。

注:選擇排序每一趟只交換一個(gè)數(shù)2暗谩!所以在每一趟比較的時(shí)候記錄下來(lái)最小的數(shù)的索引值爽蝴,在未排序序列都遍歷過(guò)一邊之后沐批,把最小的值和第一個(gè)為止的進(jìn)行交換。

def Selection_sort(myList):
   length = len(myList)
   # 總共需要length-1次蝎亚,因?yàn)榈趌ength次前面的都定了
   for i in range(length-1):
       min_index = i
       for j in range(i,length):
           if myList[j]<myList[min_index]:
               min_index = j
       if min_index != i:
           myList[i],myList[min_index]=myList[min_index],myList[i]
       print(myList)
Selection_sort([49,38,65,97,76,13,27])

插入排序(O(n^2))
思路:未排序數(shù)據(jù)九孩,在已排序序列中從后向前掃描,找到相應(yīng)位置并插入发框。

def insert_sort(myList):
    length = len(myList)
    for i in range(1,length):
        for j in range(i,0,-1):
            if myList[j]<myList[j-1]:
                myList[j],myList[j-1] = myList[j-1],myList[j]
        print(myList)
def insert_sort(myList):
    length = len(myList)
    for i in range(1,length):
        if myList[i]<myList[i-1]:
            index = i
            temp = myList[i]
            while index>0 and myList[index-1]>temp:
                myList[index]=myList[index-1]
                index = index-1
            myList[index] = temp

insert_sort([49,38,65,97,76,13,27,49])

快速排序(O(nlogn))
思想:
算法-快速排序-python3實(shí)現(xiàn)
講的很好的視頻

def QuickSort(myList,start,end):
    i,j = start,end
    base = myList[i]
    while i<j:
        while i<j and myList[j]>=base:
            j = j-1
        myList[i]=myList[j]
        while i<j and myList[i]<=base:
            i=i+1
        myList[j]=myList[i]
    myList[i] = base
    QuickSort(myList,start,i-1)
    QuickSort(myList,j+1,end)






myList = [49,38,65,97,76,13,27,49]
print("Quick Sort: ")
QuickSort(myList,0,len(myList)-1)
print(myList)

快速排序2:

def quick_sort(self,lst):
        if not lst:
            return []
        pivot = lst[0]
        left = self.quick_sort([x for x in lst[1: ] if x < pivot])
        right = self.quick_sort([x for x in lst[1: ] if x >= pivot])
        
        return left + [pivot] + right

歸并排序:
實(shí)質(zhì)其實(shí)就是合并兩個(gè)有序的列表

def merge_sort(collection):
    if len(collection)<=1:
        return collection
    mid = len(collection) // 2
    return merge(merge_sort(collection[:mid]), merge_sort(collection[mid:]))

def merge(left,right):
        result=[]
        while left and right:
            result.append(left.pop(0) if left[0]<=right[0] else right.pop(0))
        return result+left+right

print(merge_sort([2,-1,0,3,1,9]))

堆排序:
1??Python實(shí)現(xiàn):
堆排序的Python實(shí)現(xiàn)(附詳細(xì)過(guò)程圖和講解)
主要的思想是先構(gòu)建一個(gè)大根堆躺彬,然后讓大根堆的頂點(diǎn)與堆右下角的元素交換,再構(gòu)建成大根堆梅惯。
堆宪拥,其實(shí)就是一個(gè)完全二叉樹(shù),特點(diǎn)是根節(jié)點(diǎn)的值最大(大根堆)或者最邢臣酢(小根堆)
2??Python調(diào)用heaq庫(kù) (參考這篇文章Python標(biāo)準(zhǔn)庫(kù)模塊之heapq

# 使用heaq庫(kù)構(gòu)建堆
import heapq
nums = [2, 3, 5, 1, 54, 23, 132]
heap = []
for num in nums:
    heapq.heappush(heap, num)
#heapq.heappop() 函數(shù)彈出堆中最小值
print([heapq.heappop(heap) for _ in range(len(nums))])
#獲取堆中的最大或最小的范圍值
print(heapq.nlargest(3, nums))
print(heapq.nsmallest(3, nums))

4.常見(jiàn)算法
窮舉法
貪心法:典型例子是最大連續(xù)子數(shù)組和(不太確定下面這個(gè)是不是用貪心法做的)

class Solution:
    def FindGreatestSumOfSubArray(self, array):
        # write code here
        if not array:
            return 0
        
        cur_sum = 0
        max_sum = array[0]
        
        for i in range(len(array)):
            if cur_sum <= 0:
                cur_sum = array[i]
            else:
                cur_sum += array[i]
                
            if cur_sum > max_sum:
                max_sum = cur_sum
                
        return max_sum

分治法 :典型例子有快排
回溯法:例子有那個(gè)左上到右下的棋盤
動(dòng)態(tài)規(guī)劃 :

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末她君,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子葫哗,更是在濱河造成了極大的恐慌缔刹,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件劣针,死亡現(xiàn)場(chǎng)離奇詭異校镐,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)捺典,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門鸟廓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人辣苏,你說(shuō)我怎么就攤上這事『灏” “怎么了稀蟋?”我有些...
    開(kāi)封第一講書人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)呐赡。 經(jīng)常有香客問(wèn)我退客,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任萌狂,我火速辦了婚禮档玻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘茫藏。我一直安慰自己误趴,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布务傲。 她就那樣靜靜地躺著凉当,像睡著了一般。 火紅的嫁衣襯著肌膚如雪售葡。 梳的紋絲不亂的頭發(fā)上看杭,一...
    開(kāi)封第一講書人閱讀 49,046評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音挟伙,去河邊找鬼楼雹。 笑死,一個(gè)胖子當(dāng)著我的面吹牛尖阔,可吹牛的內(nèi)容都是我干的贮缅。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼诺祸,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼携悯!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起筷笨,我...
    開(kāi)封第一講書人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤憔鬼,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后胃夏,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體轴或,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年仰禀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了照雁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡答恶,死狀恐怖饺蚊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情悬嗓,我是刑警寧澤污呼,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站包竹,受9級(jí)特大地震影響燕酷,放射性物質(zhì)發(fā)生泄漏籍凝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一苗缩、第九天 我趴在偏房一處隱蔽的房頂上張望饵蒂。 院中可真熱鬧,春花似錦酱讶、人聲如沸退盯。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)得问。三九已至,卻和暖如春软免,著一層夾襖步出監(jiān)牢的瞬間宫纬,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工膏萧, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留漓骚,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓榛泛,卻偏偏與公主長(zhǎng)得像蝌蹂,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子曹锨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 有頭鏈表(注意:頭結(jié)點(diǎn)有的地方是全局變量) 初學(xué)者學(xué)自于大話數(shù)據(jù)結(jié)構(gòu)孤个,不足及錯(cuò)誤的地方請(qǐng)讀者提出來(lái),謝謝沛简。 可加 ...
    lxr_閱讀 786評(píng)論 0 2
  • 搞懂單鏈表常見(jiàn)面試題 Hello 繼上次的 搞懂基本排序算法齐鲤,這個(gè)一星期,我總結(jié)了椒楣,我所學(xué)習(xí)和思考的單鏈表基礎(chǔ)知識(shí)...
    醒著的碼者閱讀 4,575評(píng)論 1 45
  • 下雨過(guò)后的晴天 是那樣的放芒光彩 在雨水下落的瞬間 是我想念你的時(shí)刻 在雨水親吻大地的象征 是我對(duì)你的思念 雨水洗...
    半分微涼閱讀 170評(píng)論 0 0
  • 剛下高鐵给郊,聽(tīng)到了外面的雨聲,走到出站口捧灰,一陣?yán)滹L(fēng)過(guò)來(lái)淆九,沒(méi)有去在意叫的車,反而第一時(shí)間打開(kāi)天氣毛俏,廣州22度炭庙,刷的一下...
    麻花可樂(lè)閱讀 406評(píng)論 0 1
  • 第二章——?dú)w家之旅 在藏區(qū)有走走停停了大半個(gè)月,在藏區(qū)的徒步旅程基本上接近尾聲了煌寇,再繼續(xù)往下走下去焕蹄,將進(jìn)入危險(xiǎn)的藏...
    滄云隱閱讀 246評(píng)論 0 0