數據結構與算法(python版)


ADT抽象數據類型(ADT:Abstract Data Type): ADT是對數據進行處理的一種邏輯描述,並不涉及如何實現這些處理.
同一ADT可以采用不同的數據結構來實現: 1、采用程序設計語言的控制結構和基本數據。 2、類型來實現ADT所提供的邏輯接口

 

 

一、程序和算法的區別
      1、算法是對問題解決的分步描述;
      2、程序則是采用某種編程語言實現的算法,同一個算法通過不同的程序員采用不同的編程語言,能產生很多程序;

案例程序:

def sumOfN(n):
"""累計求和""" theSum
= 0 for i in range(1,n+1): theSum = theSum+i return theSum

 

 

 

 

 二、計算資源指標

        2.1、那么何為計算資源?
               ❖一種是算法解決問題過程中需要的存儲空間或內存;(但存儲空間受到問題自身數據規模的變化影響要區分哪些存儲空間是問題本身描述所需,哪些是算法占用)
               ❖另一種是算法的執行時間
 

 三、Python中有一個time模塊,可以獲取計算機系統當前時間

         3.1、算法開始前和結束后分別記錄系統時間,即可得到運行時間

               

 

 

# 使用timeit模塊對函數計時 # 創建一個timer對象,指定需要反復運行的語句

from timeit import Timer t1 = Timer("test1()", "from __main__ import test1") print("concat %f seconds\n" % (t1.timeit(number=1000))) t2 = Timer("test2()", "from __main__ import test2") print("append %f seconds\n" % (t2.timeit(number=1000)))

 

 

 四、數量級函數 Order of Magnitude,大O表示法

   1、基本操作數量函數T(n)的精確值並不是特別重要,重要的是T(n)中起決定性因素的主導部分用動態的眼光看,就是當問題規模增大的時候,

         T(n)中的一些部分會蓋過其它部分的貢獻;

   2、數量級函數描述了T(n)中隨着n增加而增加速度最快的主導部分稱作“大O”表示法,記作O(f(n)),其中f(n)表示T(n)中的主導部分;

                          

 

 

 

 

 

 算法案例:“變位詞”判斷問題

 

所謂“變位詞”是指兩個詞之間存在組成字母的
重新排列關系
如:heart和earth,python和typhon
為了簡單起見,假設參與判斷的兩個詞僅由小寫
字母構成,而且長度相等

def anagramSolution2(s1, s2):
"""將字符串變成列表並排序,然后逐一對比""" alist1
= list(s1) alist2 = list(s2) alist1.sort() alist2.sort() pos = 0 matches = True while pos < len(s1) and matches: if alist1[pos] == alist2[pos]: pos = pos + 1 else: matches = False return matches
# 使用timeit模塊對函數計時 # 創建一個timer對象,指定需要反復運行的語句

from timeit import Timer t1 = Timer("test1()", "from __main__ import test1") print("concat %f seconds\n" % (t1.timeit(number=1000))) t2 = Timer("test2()", "from __main__ import test2") print("append %f seconds\n" % (t2.timeit(number=1000)))

 

 

五、python數據類型-線性結構:list、dict、stack、queue、Deque、UnorderedList、OrderedList

  讓最常用的操作性能最好犧牲不太常用的操作 80/20准則:80%的功能其使用率只有20%
 
  5.1、什么是線性結構Linear Structure?
        
  5.2、棧Stack,隊列Queue,雙端隊列Deque和列表List
    這些數據集的共同點在於,數據項之間只存在先后的次序關系,都是線性結構
 
 
 
六、 棧stack:一種有次序的數據項集合,在棧中,數據項的加入和移除都僅發生在同一端,Last in First out

           這一端叫棧“頂top”,另一端叫棧“底base”,日常生活中有很多棧的應用:盤子、托盤、書堆等等
           應用場景:
           6.1、瀏覽器的“后退back”按鈕,最先back的是最近訪問的網頁
      6.2、 Word的“Undo”按鈕,最先撤銷的是最近操作
                 

 

                

 stack的實現:

class Stack: """簡單實現的一個棧"""
    def __init__(self): self.items = [] def isEmpty(self): return self.items == [] def push(self, item): self.items.append(item) def pop(self): return self.items.pop() #這里的:不同的方法,有不同的操作
    # def push(self, item):
    # self.items.insert(0,item)
    # def pop(self):
    # return self.items.pop(0)

    def peek(self): return self.items[len(self.items) - 1] def size(self): return len(self.items)
 
 
棧的應用一:簡單括號匹配((((()))))
class Stack: """簡單實現的一個棧"""
    def __init__(self): self.items = [] def isEmpty(self): return self.items == [] def push(self, item): self.items.append(item) def pop(self): return self.items.pop() #這里的
    # def push(self, item):
    # self.items.insert(0,item)
    # def pop(self):
    # return self.items.pop(0)

    def peek(self): return self.items[len(self.items) - 1] def size(self): return len(self.items)
def parChecker(symbolString):
    s = Stack()
    balanced = True
    index = 0
    while index < len(symbolString) and balanced:
        symbol = symbolString[index]
        if symbol == "(":
            s.push(symbol)
        else:
            if s.isEmpty():
                balanced = False
            else:
                s.pop()
        index = index + 1
    if balanced and s.isEmpty():
        return True
    else:
        return False

print (parChecker('((((()))))'))

 

通用的寫發 包含[{( 

def parChecker(symbolString): s = Stack() balanced = True index = 0 while index < len(symbolString) and balanced: symbol = symbolString[index]if symbol in "({[": s.push(symbol) else: if s.isEmpty(): balanced = False else: top=s.pop() if not matches(top,symbol): balanced = False index = index + 1
        print('s', s) if balanced and s.isEmpty(): return True else: return False def matches(open, close): opens = "[({" closers = "]})"
return opens.index(open) == closers.index(close)


實用場景

 

 

 

 

 

 棧的應用二:進制之間的轉化

   基本概念:二進制:二進制是計算機原理中最基本的概念,作為組成計算機最基本部件的邏輯門電路,其輸入和輸出
                      均僅為兩種狀態:0和1;


                     十進制:人類傳統文化中最基本的數值概念,如果沒有進制之間的轉換,人們跟計算機的交互
                     會相當的困難;

所謂的“進制”,就是用多少個字符來表示整數:十進制是0~9這十個數字字符,二進制是0、1兩
個字符
十進制轉換為二進制,采用的是“除以2求余數”的算法

 

 

 

十進制轉化為2進制 案例
def
divideBy2(decNumber): remstack =Stack() while decNumber>0: rem=decNumber%2 #求余數 remstack.push(rem) decNumber = decNumber//2 # 整數部分 binString = "" while not remstack.isEmpty(): binString=binString+str(remstack.pop()) return binString print (divideBy2(256))


十進制轉換為十六以下任意進制 def baseConverter(decNumber,base): digits="0123456789ABCDEF" remstack =Stack() while decNumber>0: rem=decNumber%base #余數
 remstack.push(rem) decNumber = decNumber//base # 整數部分
    newString = ""
    while not remstack.isEmpty(): newString=newString+digits[remstack.pop()] return newString print (baseConverter(256,2))

 

 

 棧的應用三:表達式應用

 

 

 

def infixToPostfix(infixexpr): prec = {} prec["*"] = 3  # 記錄操作符優先級
    prec["/"] = 3 prec["+"] = 2 prec["-"] = 2 prec["("] = 1 opStack = Stack() postfixList = [] tokenList = infixexpr.split()  # 解析表達式到單詞列表
    for token in tokenList: if token in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or token in "0123456789": postfixList.append(token) elif token == "(": opStack.push(token) elif token == ")": topToken = opStack.pop() while topToken != '(': postfixList.append(topToken) topToken = opStack.pop() else:  # 操作符
            while (not opStack.isEmpty()) and (prec[opStack.peek()] >= prec[token]): postfixList.append((opStack.pop())) opStack.push(token) while not opStack.isEmpty(): postfixList.append(opStack.pop()) # 操作符
        return " ".join(postfixList)  # 合成后綴表達式字符串

 

 

 七:隊列Queue:新加入的數據項必須在數據集末尾等待,而等待時間最長的數據項則是隊首;(FIFO:First-in-first-out)先進先出

      應用場景:計算機科學中隊列的例子:鍵盤緩沖❖鍵盤敲擊並不馬上顯示在屏幕上需要有個隊列性質的緩沖區,將尚未顯示的敲擊
                        字符暫存其中,
      特性:隊列的先進先出性質則保證了字符的輸入和顯示次序一致性。
      Queue():創建一個空隊列對象,返回值為Queue對象;
      enqueue(item):將數據項item添加到隊尾,無返回值;
      dequeue():從隊首移除數據項,返回值為隊首數據項,隊列被修改;
      isEmpty():測試是否空隊列,返回值為布爾值
      size():返回隊列中數據項的個數。

class Queue: def __init__(self): self.items = [] def isEmpty(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) 

 

 
            

 

enqueue()復雜度為O(n)
dequeue()復雜度為O(1)
def hotPotato(namelist, num): simqueue = Queue() for name in namelist: simqueue.enqueue(name) while simqueue.size() > 1: for i in range(num): simqueue.enqueue(simqueue.dequeue()) simqueue.dequeue() return simqueue.dequeue()

 

 

 

 

 

       

 

 

 

五、list:最常用的是:按索引取值和賦值(v =a[i], a[i]= v)、線性結構:【】

四種生成向list里面加數據的方式

def
test1(): l = [] for i in range(1000):
          '循環連接列表(+)'
        l = l + [i]


def test2():
    l = []
    for i in range(1000):
        l.append(i)


def test3():
'
列表推導式'
    l = [i for i in range(1000)]


def test4():
    l = list(range(1000))

 

 

 

 

 

 

 

 

 

 

 

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM