线性结构
线性结构包括:栈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())