[1]栈,队列,链表
栈(盘子)
栈是一种特殊的列表,栈内的元素只能通过列表的一端访问,这一端称为栈顶。咖啡厅内的一摞盘子是现实世界中常见的栈的例子。只能从最上面取盘子,盘子洗净后,也只能摞在这一摞盘子的最上面。栈被称为一种后入先出(LIFO,last-in-first-out)的数据结构。
由于栈具有后入先出的特点,所以任何不在栈顶的元素都无法访问。为了得到栈底的元素,必须先拿掉上面的元素。
对栈的两种主要操作是将一个元素压入栈和将一个元素弹出栈。入栈使用push()方法,出栈使用pop()方法。下图演示了入栈和出栈的过程。
另一个常用的操作是预览栈顶的元素。pop()方法虽然可以访问栈顶的元素,但是调用该方法后,栈顶元素也从栈中被永久性地删除了。peek()方法则只返回栈顶元素,而不删除它。
为了记录栈顶元素的位置,同时也为了标记哪里可以加入新元素,我们使用变量top,当向栈内压入元素时,该变量增大;从栈内弹出元素时,该变量减小。
push()、pop()和peek()是栈的3个主要方法,但是栈还有其他方法和属性。
stack通常的操作:
Stack() 建立一个空的栈对象
push() 把一个元素添加到栈的最顶层
pop() 删除栈最顶层的元素,并返回这个元素
peek() 返回最顶层的元素,并不删除它
isEmpty() 判断栈是否为空
size() 返回栈中元素的个数
简单案例以及操作结果:
Stack Operation | Stack Contents | Return Value |
---|---|---|
s.isEmpty() | [] | True |
s.push(4) | [4] | |
s.push(‘dog’) | [4,’dog’] | |
s.peek() | [4,’dog’] | ‘dog’ |
s.push(True) | [4,’dog’,True] | |
s.size() | [4,’dog’,True] | 3 |
s.isEmpty() | [4,’dog’,True] | False |
s.push(8.4) | [4,’dog’,True,8.4] | |
s.pop() | [4,’dog’,True] | 8.4 |
s.pop() | [4,’dog’] | True |
s.size() | [4,’dog’] | 2 |
这里使用python的list对象模拟栈的实现:
class Stack: """模拟栈""" def __init__(self): self.items = [] def isEmpty(self): return len(self.items)==0 def push(self, item): self.items.append(item) def pop(self): return self.items.pop() def peek(self): if not self.isEmpty(): return self.items[len(self.items)-1] def size(self): return len(self.items)
创建一个栈对象,并加入操作方法:
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())
输出
True dog 3 False 8.4 True 2
队列(银行排队)
队列是一种列表,不同的是队列只能在队尾插入元素,在队首删除元素。队列用于存储按顺序排列的数据,先进先出,这点和栈不一样,在栈中,最后入栈的元素反而被优先处理。可以将队列想象成在银行前排队的人群,排在最前面的人第一个办理业务,新来的人只能在后面排队,直到轮到他们为止。
队列是一种先进先出(First-In-First-Out,FIFO)的数据结构。队列被用在很多地方,比如提交操作系统执行的一系列进程、打印任务池等,一些仿真系统用队列来模拟银行或杂货店里排队的顾客。
队列的另外一项重要操作是读取队头的元素。这个操作叫做peek()。该操作返回队头元素,但不把它从队列中删除。除了读取队头元素,我们还想知道队列中存储了多少元素,可以使用size()满足该需求。
queue通常的操作:
Queue() 定义一个空队列,无参数,返回值是空队列。
enqueue(item) 在队列尾部加入一个数据项,参数是数据项,无返回值。
dequeue() 删除队列头部的数据项,不需要参数,返回值是被删除的数据,队列本身有变化。
isEmpty() 检测队列是否为空。无参数,返回布尔值。
size() 返回队列数据项的数量。无参数,返回一个整数。
队列操作举例:
Queue Operation | Queue Contents | Return Value |
---|---|---|
q.isEmpty() | [] | True |
q.enqueue(4) | [4] | |
q.enqueue(‘dog’) | [‘dog’,4] | |
q.enqueue(True) | [True,’dog’,4] | |
q.size() | [True,’dog’,4] | 3 |
q.isEmpty() | [True,’dog’,4] | False |
q.enqueue(8.4) | [8.4,True,’dog’,4] | |
q.dequeue() | [8.4,True,’dog’] | 4 |
q.dequeue() | [8.4,True] | ‘dog’ |
q.size() | [8.4,True] | 2 |
Queue 类模拟:
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)
以下是测试代码:
q=Queue() q.isEmpty() q.enqueue('dog') q.enqueue(4) q=Queue() q.isEmpty() q.enqueue(4) q.enqueue('dog') q.enqueue(True)
链表
链表由一系列不必在内存中相连的结构构成,这些对象按线性顺序排序。每个结构含有表元素和指向后继元素的指针。
最后一个单元的指针指向NULL。为了方便链表的删除与插入操作,可以为链表添加一个表头。
删除操作可以通过修改一个指针来实现。
插入操作需要执行两次指针调整。
1. 单向链表的实现
1.1 Node实现
每个Node分为两部分。一部分含有链表的元素,可以称为数据域;另一部分为一指针,指向下一个Node。
class Node(): __slots__=['_item','_next'] #限定Node实例的属性 def __init__(self,item): self._item=item self._next=None #Node的指针部分默认指向None def getItem(self): return self._item def getNext(self): return self._next def setItem(self,newitem): self._item=newitem def setNext(self,newnext): self._next=newnext
1.2 SinglelinkedList的实现
lass SingleLinkedList(): def __init__(self): self._head=None #初始化链表为空表 self._size=0
1.3 检测链表是否为空
def isEmpty(self): return self._head==None