一、栈
1.定义及特点
(1)定义:
栈(stack)是一种只能在同一端进行插入或删除操作的线性表。
(2)主要特点:
1. 后进先出,即后进栈的元素先出栈。
2. 每次进栈的元素都作为新栈顶元素,每次出栈的元素只能是当前栈顶元素。
3. 栈也称为后进先出表或者先进后出表。
2. 栈的顺序存储结构及其基本运算算法实现
(1)顺序栈:
四要素:
① 栈空条件:len(data)==0或者not data。
② 栈满条件:由于data列表可以动态扩展,所以不必考虑栈满。
③ 元素e进栈操作:将e添加到栈顶处。
④ 出栈操作:删除栈顶元素并返回该元素。
class SqStack:
def __init__(self): #构造方法
self.data=[] #存放栈中元素,初始为空
基本运算:
1)判断栈是否为空empty()
def empty(self): #判断栈是否为空
if len(self.data)==0:
return True
return False
2)进栈push(e)
def push(self,e): #元素e进栈
self.data.append(e)
3)出栈pop()
def pop(self): #元素出栈
assert not self.empty() #检测栈为空
return self.data.pop()
4)取栈顶元素gettop()
def gettop(self): #取栈顶元素
assert not self.empty() #检测栈为空
return self.data[-1]
(2)双栈
设有两个栈S1和S2,它们都采用顺序栈存储,并且共享一个固定容量的存储区s[0..M-1],为了尽量利用空间,减少溢出的可能,请设计这两个栈的存储方式。
栈S1空的条件是top1=-1。
栈S1满的条件是top1=top2-1;
元素e进栈S1(栈不满时)的操作是:top1++;s[top1]=e。
元素e出栈S1(栈不空时)的操作是:e=s[top1];top1--。
栈S2空的条件是top2=M。
栈S2满的条件是top2=top1+1。
元素e进栈S2(栈不满时)的操作是:top2--;s[top2]=e。
元素e出栈S2(栈不空时)的操作是:e=s[top2];top2++
3.栈的链式存储结构及其基本运算算法实现
class LinkNode: #单链表结点类
def __init__(self,data=None): #构造方法
self.data=data #data属性
self.next=None #next属性
class LinkStack: #链栈类
def __init__(self): #构造方法
self.head=LinkNode() #头结点head
self.head.next=None
基本运算:
1)判断栈是否为空empty()
def empty(self): #判断栈是否为空
if self.head.next==None:
return True
return False
2)进栈push(e)
def push(self,e): #元素e进栈
p=LinkNode(e)
p.next=self.head.next
self.head.next=p
3)出栈pop()
def pop(self): #元素出栈
assert self.head.next!=None #检测空栈的异常
p=self.head.next;
self.head.next=p.next
return p.data
4)取栈顶元素gettop()
def gettop(self): #取栈顶元素
assert self.head.next!=None #检测空栈的异常
return self.head.next.data
二、队列
1.定义及特点
(1)定义:
队列(queue)是一种只能在不同端进行插入或删除操作的线性表。
(2)主要特点:
1. 先进先出,即先进队的元素先出队。
2. 每次进队的元素作为新队尾元素,每次出队的元素只能是队头的元素。
3. 队列也称为先进先出表。
2.队列的顺序存储结构及其基本运算算法实现
(1)非循环队列
四要素:
1. 队空条件:front==rear。
2. 队满(上溢出)条件:rear==MaxSize-1(因为每个元素进队都让rear增1,当rear到达最大下标时不能再增加。
3. 元素e进队操作:rear增1,将元素e放在该位置(进队的元素总是在尾部插入的)。
4. 出队操作:front增1,取出该位置的元素(出队的元素总是在队头出来的)。
MaxSize=100 #假设容量为100
class SqQueue: #非循环队列类
def __init__(self): #构造方法
self.data=[None]*MaxSize #存放队列中元素
self.front=-1 #队头指针
self.rear=-1 #队尾指针
基本运算:
1)判断队列是否为空empty()
def empty(self): #判断队列是否为空
return self.front==self.rear
2)进队push(e)
def push(self,e): #元素e进队
assert not self.rear==MaxSize-1 #检测队满
self.rear+=1
self.data[self.rear]=e
3)出队pop()
def pop(self): #出队元素
assert not self.empty() #检测队空
self.front+=1
return self.data[self.front]
4)取队头元素gethead()
def gethead(self): #取队头元素
assert not self.empty() #检测队空
return self.data[self.front+1]
(2)循环队列
四要素:
1. 队空条件:rear==front。
2. 队满条件:(rear+1)%MaxSize==front(相当于试探进队一次,若rear达到front,则认为队满了)。
3. 元素e进队:rear=(rear+1)%MaxSize,将元素e放置在该位置。
4. 元素出队:front=(front+1)%MaxSize,取出该位置的元素。
MaxSize=100 #全局变量,假设容量为100
class CSqQueue: #循环队列类
def __init__(self): #构造方法
self.data=[None]*MaxSize #存放队列中元素
self.front=0 #队头指针
self.rear=0 #队尾指针
基本运算:
1)判断队列是否为空empty()
def empty(self): #判断队列是否为空
return self.front==self.rear
2)进队push(e)
def push(self,e): #元素e进队
assert (self.rear+1)%MaxSize!=self.front #检测队满
self.rear=(self.rear+1)%MaxSize
self.data[self.rear]=e
3)出队pop()
def pop(self): #出队元素
assert not self.empty() #检测队空
self.front=(self.front+1)%MaxSize
return self.data[self.front]
4)取队头元素gethead()
def gethead(self): #取队头元素
assert not self.empty() #检测队空
head=(self.front+1)%MaxSize #求队头元素的位置
return self.data[head]
3.队列的链式存储结构及其基本运算算法实现
四要素:
1. 队空条件:fronr=rear==None,不妨仅以front==None作为队空条件。
2. 由于只有内存溢出时才出现队满,通常不考虑这样的情况。
3. 元素e进队操作:在单链表尾部插入存放e的s结点,并让队尾指针指向它。
4. 出队操作:取出队首结点的data值并将其从链队中删除。
class LinkNode: #链队结点类
def __init__(self,data=None): #构造方法
self.data=data #data属性
self.next=None #next属性
class LinkQueue: #链队类
def __init__(self): #构造方法
self.front=None #队头指针
self.rear=None #队尾指针
基本运算:
1)判断队列是否为空empty()
def empty(self): #判断队是否为空
return self.front==None
2)进队push(e)
def push(self,e): #元素e进队
s=LinkNode(e) #新建结点s
if self.empty(): #原链队为空
self.front=self.rear=s
else: #原链队不空
self.rear.next=s #将s结点链接到rear结点后面
self.rear=s
3)出队pop()
def pop(self): #出队操作
assert not self.empty() #检测空链队
if self.front==self.rear: #原链队只有一个结点
e=self.front.data #取首结点值
self.front=self.rear=None #置为空队
else: #原链队有多个结点
e=self.front.data #取首结点值
self.front=self.front.next #front指向下一个结点
return e
4)取队头元素gethead()
def gethead(self): #取队头元素
assert not self.empty() #检测空链队
e=self.front.data #取首结点值
return e
双端队列deque