Python数据结构与算法分析(第2版) —— 第1章 导论 and 第2章 算法分析 and 第3章 基本数据结构

Python数据结构与算法分析(第2版) —— 第1章 导论 and 第2章 算法分析 and 第3章 基本数据结构

1.4 Python基础

快速初始化列表

myList = [0] * 6
print(myList)

快速建立“矩阵”

myList = [0] * 6
A = [myList] *3
print(A)

Python列表提供的方法

在这里插入图片描述

print((54).__add__(21)) # 75

Python字符串提供的方法

在这里插入图片描述

Python集合支持的运算

在这里插入图片描述

Python集合提供的方法
在这里插入图片描述

Python字典支持的运算

在这里插入图片描述

Python字典提供的方法

在这里插入图片描述

1.4.2 输入与输出
print("Hello","world",sep = "***",end=" ")

格式化字符串可用的类型声明

在这里插入图片描述

格式化修改符

在这里插入图片描述

2.2.1 大O记法

当问题规模为n时,解决问题所需的时间是T(n)

随着问题规模的增长,T(n)函数的某一部分会比其余部分增长得更快。数量级 → 当n增长时,T(n)增长最快的部分。

数量级常被称作大O记法,记作O(f(n))

常见的大O函数

在这里插入图片描述

2.2.2 异序词检测示例

如果一个字符串只是重排了另一个字符串的字符,那么这个字符串就是另一个的异序词,比如heart和earth,以及python和typhon。

计数法

def anagramSolution(s1,s2):
    c1 = [0] * 26
    c2 = [0] * 26

    for i in range(len(s1)):
        pos = ord(s1[i]) - ord("a")
        c1[pos] = c1[pos] + 1

    for i in range(len(s2)):
        pos = ord(s2[i]) - ord("a")
        c2[pos] = c2[pos] + 1

    j = 0
    stillOK = True
    while j < 26 and stillOK:
        if c1[j] == c2[j]:
            j = j + 1
        else:
            stillOK = False
    return stillOK

s1 = "heart"
s2 = "earth"
print(anagramSolution(s1,s2))

2.3 Python数据结构的性能

2.3.1 列表

创建列表

l = list(range(1000))
print(l)
2.3.2 字典

在包含操作中,字典速度比列表更快

3.2 线性数据结构

一旦某个元素被添加进来,它与前后元素的相对位置将保持不变。这样的数据集合经常被称为线性数据结构。

3.3 栈

LIFO(last-in first-out),后进先出

3.3.3 用Python实现栈
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 peek(self):
        return self.items[len(self.items) - 1]
    # 返回栈中元素的数目
    def size(self):
        return len(self.items)

也可以将列表的头部作为栈的顶端

3.3.4 匹配括号

from pythonds.basic import Stack

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 += 1
    if balanced and s.isEmpty():
        return True
    else:
        return False

s = "((()))"
print(parChecker(s))
3.3.5 普通情况:匹配符号
from pythonds.basic import Stack

def matches(open,close):
    opens = "([{"
    closes = ")]}"
    return opens.index(open) == closes.index(close)

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 += 1
    if balanced and s.isEmpty():
        return True
    else:
        return False

s = "([{}])"
print(parChecker(s))

3.3.6 将十进制数转换成任意进制数

from pythonds.basic import Stack

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

x = 4
print(baseConverter(x,2))
3.3.7 前序、中序和后序表达式

在这里插入图片描述

前序表达式和后序表达式是的运算顺序完全由运算符的位置决定

用Python实现从中序表达式到后序表达式的转换

from pythonds.basic import Stack
import string

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 string.ascii_uppercase:
            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)

s = "( A + B ) * ( C + D )"
print(infixToPostfix(s))

用Python实现后序表达式的计算

from pythonds.basic import Stack
def doMath(op,op1,op2):
    if op == "*":
        return op1 * op2
    elif op == "/":
        return op1 / op2
    elif op == "+":
        return op1 + op2
    else:
        return op1 - op2


def postfixEval(postfixExpr):
    operandStack = Stack()

    tokenList = postfixExpr.split()
    for token in tokenList:
        if token in "0123456789":
            operandStack.push(int(token))
        else:
            operand2 = operandStack.pop()
            operand1 = operandStack.pop()
            result = doMath(token,operand1,operand2)
            operandStack.push(result)

    return operandStack.pop()

s = "4 5 6 * +"
print(postfixEval(s))

3.4 队列

FIFO(first-in first-out) 先进先出

用Python实现队列

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)

传土豆模拟程序

from pythonds.basic import Queue
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()

names = ["Bill","David","Susan","Jane","Kent","Brad"]
print(hotPotato(names,7))
3.4.5 模拟:打印任务
import random
from pythonds.basic import Queue
class Printer:
    def __init__(self,ppm):
        self.pagerate = ppm
        self.currentTask = None
        self.timeRemaining = 0

    def tick(self):
        if self.currentTask != None:
            self.timeRemaining = self.timeRemaining - 1
            if self.timeRemaining <= 0:
                self.currentTask = None

    def busy(self):
        if self.currentTask != None:
            return True
        else:
            return False

    def startNext(self,newtask):
        self.currentTask = newtask
        self.timeRemaining = newtask.getPages() * 60 / self.pagerate

class Task:
    def __init__(self,time):
        self.timestamp = time
        self.pages = random.randrange(1,21)

    def getStamp(self):
        return self.timestamp

    def getPages(self):
        return self.pages

    def waitTime(self,currenttime):
        return currenttime - self.timestamp

def newPrintTask():
    num = random.randrange(1,181)
    if num == 180:
        return True
    else:
        return False

def simulation(numSeconds,pagePerMinute):

    labprinter = Printer(pagePerMinute)
    printQueue = Queue()
    waittingtimes = []

    for currentSecond in range(numSeconds):
        if newPrintTask():
            task = Task(currentSecond)
            printQueue.enqueue(task)
        if (not labprinter.busy()) and (not printQueue.isEmpty()):
            nexttask = printQueue.dequeue()
            waittingtimes.append(nexttask.waitTime(currentSecond))
            labprinter.startNext(nexttask)

        labprinter.tick()
    averageWait = sum(waittingtimes) / len(waittingtimes)
    print("Average Wait %6.2f secs %3d tasks remaining." % (averageWait,printQueue.size()) )

for i in range(10):
    simulation(3600,5)

3.5 双端队列

双端队列对在哪一端添加和移除元素没有任何限制,新元素既可以被添加到前端,也可以被添加到后端,同理,已有的元素也能从任意一端移除。

用Python实现双端队列

class Deque:
    def __init__(self):
        self.items = []
    # 判空
    def isEmpty(self):
        return self.items == []
    # 从队头添加
    def addFront(self,item):
        self.items.append(item)
    # 从队尾添加
    def addRear(self,item):
        self.items.insert(0,item)
    # 从队头出队
    def removeFront(self):
        return self.items.pop()
    # 从队尾出队
    def removeRear(self):
        return self.items.pop(0)
    # 队大小
    def size(self):
        return len(self.items)
3.5.4 回文检测器
from pythonds.basic import Deque

def palchecker(aString):
    chardeque = Deque()

    for ch in aString:
        chardeque.addRear(ch)
    stillEqual = True

    while chardeque.size() > 1 and stillEqual:
        first = chardeque.removeFront()
        last = chardeque.removeRear()

        if first != last:
            stillEqual = False
            
    return stillEqual

s = "roor"
print(palchecker(s))

3.6 列表

3.6.2 实现无序列表:链表

节点对象包含元素及指向下一个节点的引用

Node类:

class Node:
    def __init__(self,initdata):
        self.data = initdata
        self.next = None
        
    def getData(self):
        return self.data
    
    def getNext(self):
        return self.next
    
    def setData(self,newdata):
        self.data = newdata
        
    def setNext(self,newnext):
        self.next = newnext

链表类 - 无序

class UnorderedList:
    def __init__(self):
        self.head = None

    # 判空
    def isEmpty(self):
        return self.head == None
    # 添加节点
    def add(self,item):
        temp = Node(item)
        temp.setNext(self.head)
        self.head = temp

    # 返回节点个数
    def length(self):
        current = self.head
        count = 0
        while current != None:
            count += 1
            current = current.getNext()
        return count

    # 是否存在某元素
    def search(self,item):
        current = self.head
        found = False
        while current != None and not found:
            if current.getData() == item:
                found = True
            else:
                current = current.getNext()
        return found

    # 移除某元素
    def remove(self,item):
        current = self.head
        previous = None
        found = False
        while not found:
            if current.getData() == item:
                found = True
            else:
                previous = current
                current = current.getNext()
        if previous == None:
            self.head = current.getNext()
        else:
            previous.setNext(current.getNext())

    # 在尾部添加节点
    def append(self,item):

        newnode = Node(item,None)
        temp = self.head
        if self.head == None:
            self.head = newnode
        else:
            while temp.next != None:
                temp = temp.next
            temp.next = newnode

    # 在链表中插入节点
    def insert(self,position,newdata):
        temp = self.head
        j = 0
        newnode = Node(newdata)
        if self.length() < position:
            print("error")
        else:
            while j < position - 1:
                temp = temp.next
                j += 1
            newnode.next = temp.next
            temp.next = newnode

    # 删除某个节点
    def pop(self,position):
        temp = self.head
        j = 0
        if self.length() < position:
            print("error")
        else:
            while j < position - 1:
                temp = temp.next
                j += 1
            temp.next = temp.next.next

mylist =  UnorderedList()
mylist.add(15)
mylist.add(20)
print(mylist.length())
print(mylist.search(15))
    print("error")
        else:
            while j < position - 1:
                temp = temp.next
                j += 1
            newnode.next = temp.next
            temp.next = newnode

    # 删除某个节点
    def pop(self,position):
        temp = self.head
        j = 0
        if self.length() < position:
            print("error")
        else:
            while j < position - 1:
                temp = temp.next
                j += 1
            temp.next = temp.next.next

mylist =  UnorderedList()
mylist.add(15)
mylist.add(20)
print(mylist.length())
print(mylist.search(15))
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ding Jiaxiong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值