栈和队列

225 阅读3分钟

栈和队列的定义和特点:

插入删除只能在表的 “端点” 进行的线性表

栈 后进先出(称作LIFO)

image.png 只能在队尾和队头插入删除

表尾成为栈顶Top,表头成为栈低Base

插入元素到栈顶(即表尾)的操作,成为入栈(PUSH)

从栈顶(即表尾)删除最后一个元素的操作,称为出栈(POP)

image.png

队列

只能删除第一个(队头)元素,在最后(队尾)插入

先进先出

栈(Stack)的表示和操作实现

image.png

image.png

image.png 空栈:base == top是栈空的标志

image.png 栈满:top - base == stacksize 栈满时的处理方法: 1.报错,返回操作系统 2.分配更大的空间,作为栈的存储空间,将原栈的内容移入新栈 上溢:栈满了,仍要存入 下溢:栈已经空了,仍要弹出元素 顺序栈的表示:

# define MAXSIZE 100
typedef struct{
	SElemType *base;//栈低指针
	SElemType *top;//栈顶指针
	int stacksize;//栈可用最大容量
}SqStack;

1.初始化

top 指针和 base 指向统一位置 stacksize == 0

Status InitStack(SqStack &S){
	S.base = new SElemType[MAXSIZE];
	S.base =(SElemType*)malloc(MAXSIZE*sizeof(SElemType));
	if(!S.base)
		exit(OVERFLOW);
	S.top = S.base;
	S.stacksize = MAXSIZE;
	return OK;
} 

2.销毁

image.png

Status DestroyStack(SqStack &S)
{
	if(S.base){
		delete S.base;
		S.stacksize = 0;
		S.base = S.top = NULL;
	}
	return OK;
}

3.判断S是否为空


Status StackEmpty(SqStack S){
	if (S.top == S.base)
		return TRUE;
	else
		return FALSE;
} 

4.栈的长度

int StackLength(SqStack S)
{
	return S.top - S.base;
}
//
Status ClearStack(SqStack S){
	if (S.base)
		S.top = S.base;
	return OK;
} 

5.获取栈顶元素

6.清空操作

认为他是空就可以了

栈顶指向栈尾

Status ClearStack(SqStack S){
	if(S.base)
		S.top = S.base;
	return OK;
} 

7.入栈操作

image.png 判断是否栈满,若满则出错

Status Push(SqStack &S,SElemType e){
	if(S.top - S.base == S.stacksize)//栈满
		return ERROR;
	*S.top = e;
	S.top++; //*S.top++ = e;
} 

8.出栈操作

image.png

Status Pop(SqStack &S,SElemType e)
{
	if(S.top == S.base)
		return REEOR;
	S.top--;
	e = *S.top;//两步合成一步e = *--S.top 
}

9.

队列的顺序表示和操作实现(Queue)

类型定义

//队列
typedef struct{
	QElemType *base;//初始化的分配内存空间
	int front;//头指针 若队列不为空,指向队列头元素 
	int rear; //尾指针 若队列不为空,指向队列尾元素的下一位置
}SqQueue;

image.png

真溢出:front == 0,rear = MAXQSIZE 队列已经满了,无法在插入元素

假溢出:front != 0,rear = MAXQSIZE 队列不满,如上图

解决:1.移动位置:缺点浪费时间,将剩下所有元素都移动

2.引入循环队列

image.png

base[0]接在base[MAXQSIZE - 1]之后,若rear + 1 == M,则令rear=0 实现方法:利用模运算(% 取余)

image.png

相当于

image.png

image.png 那怎么判断是队空还是队满

解决方案:少用一个元素空间

image.png

image.png

image.png

1.队列的初始化

Status InitQueue(SqQueue &Q){
	Q.base = new QElemType[MAXQSIZE] //分配数组空间
	//Q.base = (QElemType*)malloc(MAXQSIZE*sizeof(QWElemType));
	if (!Q.base) 
	{
		exit(OVERFLOW);
	}
	Q.front = Q.rear = 0;//头指针尾指针为0,队列为空
	return OK; 
}

2、求队列的长度

image.png 两种情况

第一个:rear > front Queuelength = Q.rear - Q.front

第二个:rear < front Queuelength = (Q.rear - Q.front + MAXSIZE) % MAXSIZE 例:front = 4,rear = 1 length = (1-4+6)%6 = 3

int QueueLength(SqQueue Q){
	return (Q.rear - Q.front + MAXSIZE) % MAXSIZE
}

3.入队算法

Status EnQueue(SqQueue &Q,QElemType e){
	if ((Q.rear + 1 ) % MAXSIZE == Q.front )
		return ERROR;//判断队列是否为满
	Q.base[Q.rear ] == e;//新元素加入队尾 
	Q.rear = (Q.rear + 1) % MAXQSZIE//队尾指针+1 
	return OK; 
}

4.出队

Status DeQueue(SqQueue &Q,QElemType e)
{
	if (Q.front == Q.rear )
		return ERROR;//队空
	e = Q.base[Q.front ]//保存队头元素
	Q.front = (Q.front + 1) % MAXQSIZE;
	return OK; 
}

5.取队头元素

SElemType GetHead(SqQueue Q){
	if (Q.front == Q.rear )
		return ERROR;//队列不为空 
	return Q.base[Q.front]//返回队头指针元素的值,队头指针不变 
}

队列的链式表示和实现

若用户无法估计所用队列的长度,则宜采用链队列

image.png

1.链队列的类型定义

typedef struct Qnode{
	QElemType data;
	struct Qnode *next;
}QNode,*QuenePtr;(pointer)
typedef struct {
	QuenePtr front;//队头指针
	QUenePtr rear;//队尾指针 
}LinkQueue;

链式队列运算指针变化状况 空队列

image.png 元素X入队

y入队

image.png x出队

image.png 然后将x释放

2.链队列的初始化

Status InitQueue(LinkQueue &Q)
{
	Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));
	Q.front->next = NULL;
	
	return OK;
}

3.销毁链队列

Status DestryQueue(LinkQueue &Q){
	while(Q.front )
	{
		p = Q.front->next;//先将下一节点存起来
		free(Q.front);//释放结点
		Q.front = p; //指向下一节点
	}
} 

4.将元素e入队

image.png


Status EnQueue(LinkQueue &Q,QElemType e){
	p = (QueuePtr)malloc(sizeof(QNode));
	p->data = e;
	p->next = NULL;
	Q.rear->next = p;
	Q.rear = p;//更新尾指针 
	return OK;
}

5.链队列出列

image.png

image.png

Status DeQueue(LinkQueue &Q,QElemType e){
	if(Q.front == Q.rear )//判断对空 
		return ERROR;
	p = Q.front->next;
	e = p->data;
	Q.front->next = p->next;
	if(Q.rear == p)//如果要删除的结点恰是尾节点 
		Q.rear = Q.front;
	
	free(p);
	return 
}

6.求队头元素

Status GetHead (LinkQueue Q,QElemType &e){
	if(Q.front==Q.rear)
		return ERROR;
	e=Q.front->next->data;
	return OK; 
}