数据结构与算法Python版(二)

线性结构

在这里插入图片描述

线性结构包括:栈Stack,队列Queue,双端队列Deque,列表List

几种线性结构的区别

个人理解:
①栈Stack,队列Queue,双端队列Deque都是对列表处理后封装的函数。
②列表,是数据项能够维持相对位置的数据集。
③链表,可以保持列表维持相对位置的特点,而不需要连续的存储空间。对链表头部head需要特别的处理。
④有序表,在链表的基础上,按照某种数据项进行排序。

栈Stack

定义

一种有次序的数据项集合,在栈中,数据项的加入和移除都仅发生在同一端。这一端叫做栈“顶top”,另一端叫做栈“底base”。

次序

后进先出LIFO:Last in First out

栈测试代码如下

from pythonds.basic.stack import Stack

s = Stack()

print(s.isEmpty())
s.push(4)
s.push('dog')
print(s.peek()) # 窥探’栈‘顶数据项
s.push(True)
print(s.size())
print(s.isEmpty())
s.push(8.4)
print(s.pop())
print(s.pop())
print(s.size())
print(s.items)

在这里插入图片描述

实现思想(注意,此处代码不用我们编,知道思想即可)

在这里插入图片描述
调用方法:from pythonds.basic.stack import Stack,即可直接调用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 peek(self):
        return self.items[len(self.items)-1]

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

栈的应用

十进制转换成二进制

from pythonds.basic.stack import Stack

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(233))

在这里插入图片描述

十进制转换成其他进制

在这里插入图片描述

from pythonds.basic.stack import Stack


def baseConverter(decNumber,base):
    digits = '0123456789ABCDEF'

    remstack = Stack()

    while decNumber > 0:
        rem = decNumber % base  # 这里的base替换成16进制及16进制以下的任意进制都可以
        remstack.push(rem)
        decNumber = decNumber // base  # 这里的base替换成16进制及16进制以下的任意进制都可以

    newString = ""
    while not remstack.isEmpty():
        newString = newString + digits[remstack.pop()] # 弹出栈序号然后对应digits[]数组的对应字符串

    return newString


print(baseConverter(233,2)) # 233转换成2进制和16进制
print(baseConverter(233,16))

在这里插入图片描述

队列

定义

新数据项的添加总发生在一端(尾端,rear),而现存数据项的移除总发生在另一端(首端,front)

次序

先进先出FIFO:First-in first-out

队列测试代码如下

在这里插入图片描述
在这里插入图片描述

实现思想(注意,此处代码不用我们编,知道思想即可)

在这里插入图片描述

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)

队列的应用

热土豆问题

# 注意:这个热土豆问题,要画一张图表示才直观。不能写1234567然后淘汰人,应该写1在David,一轮后,淘汰的是David。为什么1是写David?因为Bill走后就是一轮后,是David拿着土豆。

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()) # 一次传递

        print(simqueue.dequeue())

    return simqueue.dequeue()


print(hotPotato(["Bill","David","Susan","Jane","Kent","Brad"],7))

在这里插入图片描述

打印任务问题

类的使用不熟悉,有空专门出一栏类的知识。以下的代码是定义了两个类Printer和Task;定义了主函数simulation;模拟10次打印。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

from pythonds.basic.queue import Queue

import random


class Printer: # 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: # 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): # 计算任务的等待时间,currenttime表示当前时间
        return currenttime - self.timestamp


def newPrintTask():  # 1/180概率生成作业
    num = random.randrange(1,181)
    if num == 180:
        return True
    else:
        return False


# 模拟打印任务的整个过程,它接受两个参数,newSeconds表示模拟的总时间,pagesPerMinute表示打印机的打印速度
def simulation(newSeconds,pagesPerMinute):
    labprinter = Printer(pagesPerMinute)
    printQueue = Queue()
    waitingtimes = []

    for currentSecond in range(newSeconds): # 每秒钟,程序检查是否生成新的打印任务。
        if newPrintTask():  # 时间流逝
            task = Task(currentSecond)
            printQueue.enqueue(task)

        if (not labprinter.busy()) and (not printQueue.isEmpty()):
            nexttask = printQueue.dequeue()
            waitingtimes.append(nexttask.waitTime(currentSecond))
            labprinter.startNext(nexttask)

        labprinter.tick() # 模拟一秒钟的打印过程

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



# 主程序中使用simulation()函数模拟了10次打印,每次模拟的时间为3600秒(1小时),打印速度是10页/分钟。
for i in range(10):
    simulation(3600,10)

在这里插入图片描述

双端队列(Deque)

定义

双端队列(deque)中的数据项可以从队首加入,也可以从队尾加入;数据项也可以从两端移除。

次序

没有LIFO或FIFO的特性

双端队列测试代码如下

在这里插入图片描述
在这里插入图片描述

实现思想(注意,此处代码不用我们编,知道思想即可)

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)

栈的应用

回文词的判定

from pythonds.basic.deque 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

print(palchecker('lsdkjfskf'))
print(palchecker('radar'))

在这里插入图片描述

链表

链表实现:节点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

temp = Node(93)
print(temp.getData())

在这里插入图片描述

创建一个空的链表

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


mylist = UnorderedList()
print(mylist.head)

在这里插入图片描述

链表的增、长度、查找、移除操作

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


def add(self,item):
    temp = Node(item) # 创建一个新的节点
    temp.setNext(self.head) # 设置下一个地址是现在的head位置
    self.head = temp # 更新head为当下的temp节点

def size(self):
    current = self.head
    count = 0
    while current != None:
        count = 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())

有序表

定义

有序表是一种数据项依照其某可比限制(如整数大小、字母表先后)来决定在列表中的位置。越小的数据项越靠近列表的头,越靠前。
在这里插入图片描述

注意事项

1.有序表和无序表(链表)的区别

在这里插入图片描述

2.有序表的search方法

在这里插入图片描述

def search(self,item): # 有序表的search方法、add方法和链表的不一样,其他的都一样
    current = self.head
    found = False
    stop = False
    while current != None and not found and not stop:
        if current.getData() == item:
            found = True
        else:
            if current.getData() > item:
                stop = True   # 有序表和链表的search方法差别在第9、10行,以及第5行
            else:
                current = current.getNext()

    return found

3.有序表的add方法

在这里插入图片描述

def add(self,item): # 有序表的search方法、add方法和链表的不一样,其他的都一样
    current = self.head
    previous = None
    stop = False
    while current != None and not stop:
        if current.getData() > item: # 发现插入位置,如果当前位置比item大,那么就停止循环。
            stop = True
        else:
            previous = current
            current = current.getNext()

    temp = Node(item)
    if previous == None: # 插入在表头
        temp.setNext = (self.head)
        self.head = temp
    else:                # 插入在表中
        temp.setNext(current)
        previous.setNext(temp)

有序表的实现(包含前面的search和add方法)

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


def add(self,item): # 有序表的search方法、add方法和链表的不一样,其他的都一样
    current = self.head
    previous = None
    stop = False
    while current != None and not stop:
        if current.getData() > item: # 发现插入位置,如果当前位置比item大,那么就停止循环。
            stop = True
        else:
            previous = current
            current = current.getNext()

    temp = Node(item)
    if previous == None: # 插入在表头
        temp.setNext = (self.head)
        self.head = temp
    else:                # 插入在表中
        temp.setNext(current)
        previous.setNext(temp)


def size(self):
    current = self.head
    count = 0
    while current != None:
        count = count + 1
        current = current.getNext()

    return count


def search(self,item): # 有序表的search方法、add方法和链表的不一样,其他的都一样
    current = self.head
    found = False
    stop = False
    while current != None and not found and not stop:
        if current.getData() == item:
            found = True
        else:
            if current.getData() > item:
                stop = True   # 有序表和链表的search方法差别在第9、10行,以及第5行
            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())
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值