栈和队列

栈的定义和操作名称

定义

  1. 栈是限定仅可在表尾进行删除和插入的线性表
  2. 后进先出形(LIFO)的线性表

基本概念

  1. 栈顶(top)
  • 栈可删除和插入的一端
  1. 栈底(bottom)
  • 另一端为栈底
  1. 空栈
  • 没有元素的栈

操作

  1. 插入
  • 也叫进栈,压栈,入栈
  1. 删除
  • 弹栈,出栈

栈的ADT

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Data
	同线性表
Operation
	IintStack(*S):初始化建立空栈
	DestroyStack(*S): 摧毁一个栈
	ClearStack(*S):清空栈
	StackEmpty(S):栈为空,返回true,否则返回false
	GetTop(S,*e):若栈存在且非空,用e返回S的栈顶元素
	Push(*S,e):插入
	Pop(*S,*e):删除,并用e返回被删除的元素
	StackLength:返回栈S的元素个数
endADT

栈的顺序存储结构

结构定义

1
2
3
4
5
6
typedef int SElemType; //根据实际情况确定栈的元素类型
typedef struct
{
	SElemType data[MAXSIZE];
	int top;//用于栈顶指针
}SqStack;

入栈

1
2
3
4
5
6
7
8
Status Push(SqStack *S, SElemType e)
{
	if (S->top==MAXSIZE-1)//栈满
		return -1;
	S->top++;
	S->data[S->top]=e;
	return 0;
}

出栈

1
2
3
4
5
6
7
8
Status Pop(SqStack *S, SElemType *e)
{
	if (S->top==-1)//空栈
		return -1;
	*e = S->data[S->top];
	S->top--;
	return -1;
}

两栈共享空间

结构

  • 将两栈的顶部接到一起

结构代码

1
2
3
4
5
6
typedef struct
{
	SElemType data[MAXSIZE];
	int top1;
	int top2;
}SqDoubleStack

操作

  • 插入
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Status Push(SqDoubleStack *S, SElemType e, int StackNumber)
//StackNumber 用来判断插入栈1还是栈2
{
	if(S->top1++=S->top2)//栈满
		return -1;
	if(StackNumber == 1)
		S->data[++S->top1]=e;
	if(StackNumber == 2)
		S->data[--S->top2]=e;
}
  • 删除
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
Status Pop(SqDoubleStack *S, SElemType *e,int StackNumber)
{
	if (StackNumber == 1)
	{
		if (S->top1==-1)//空栈
			return -1;
		*e = S->data[S->top1];
		top1++;
	}
	if (StackNumber == 2)
	{
		if (S->top2 == MAXSIZE)//空栈
			return -1;
		*e = S->data[S->top2];
		top2--;
	}
	return 0;
}

栈的链式存储结构

定义

  • 简称链栈

特点

  • 栈顶在头部
  • 没有头结点

结构代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
typedef struct StackNode
{
	SElemType data;
	struct StackNode *next;
} StackNode,*LinkStackPtr;

typedef struct LinkStack
{
LinkStackPtr top;
int count;
}LinkStack;

操作

进栈

1
2
3
4
5
6
7
8
Status Push(LinkStack *S, SElemType e)
{
	LinkStackPtr s = (LinkStackPtr) malloc(sizeof(StackNode));
	s->data=e;
	s->next=S->top;
	S->count++;
	return 0;
}

出栈

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Status Pop(LinkStack *S, SElemType *e)
{
	LinkStackPtr p;
	if (StackEmpty(*S))//空栈
		return -1;
	*e = S->top->data;
	p = S->top;
	S->top=S->top->next;
	free(p);
	S->count--;
	return 0;
}

栈的应用

递归

斐波那契数列

  1. 数学定义

$$ F(n)=\begin{cases}0 & n=0 \\ 1 & n=1 \\ F(n-1)+F(n-2) & n \ge 2\end{cases} $$

  1. 代码实现
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
int Fib(int n)
{
	if (n == 0)
		return 0;
	else if (n==1)
		return 1;
	else 
		return F(n-1)+F(n-2);
}

int main()
{
	int i = 0;
	for(i=0;i<40;i++)
	{
		printf("%d",Fib(n));
	}
	return 0;
}

文字定义

调用自己的函数(包括直接和间接)称作递归函数

四则运算表达式求值

后缀表达式

  1. 原则
  • 数字依次进栈
  • 有运算符号,出两个数字
    • 下面的数字在运算符号前
    • 上面的数字在运算符号后

9 3 1 - 3 * + 10 2 / + = 20

中缀表达式转后缀表达式

  1. 中缀表达式就是平时用到的表达式

  2. 转换

  • 数字按顺序输出

  • 符号依次进栈

  • 若下方的符号运算优先级高于上方,输出该符号及其上方的符号

队列(FIFO)

定义

只允许在一端插入,另一端删除的线性表

  1. 队尾
  • 只允许插入的一端
  1. 队头
  • 只允许删除的一端

ADT

1
2
3
4
Data
	同线性表,有前驱和后继,元素类型相同
Operation
	

循环队列

定义

队列的头尾相连顺序存储结构

结构 初始化 长度

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 结构定义
typedef int QElemType;
typedef struct
{
QElemType data[MAXSIZE];
int front;
int rear;
}SqQueue;

// 初始化

Status Sqinit(SqQueue *Q)
{
Q->front = 0;
Q->rear = 0;
return 0;
}

// 长度

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

入列和出列

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// 入列

Status EnQueue(SqQueue *Q,QElemType e)
{
	if ((Q->rear + 1) == Q->front)
		return -1;
	Q->data[Q->rear] = e;
	Q->rear = (Q->rear+1)%MAXSIZE;
	return 0;
}

// 出列

Status DeQueue(SqQueue *Q, QElemType *e)
{
	if (Q->rear == Q->front)
		return -1;
	*e=Q->data[Q->front];
	Q->front = (Q->front + 1)% MAXSIZE;
}

队列的链式存储结构

定义

线性表的单链表,称为链队列

结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
typedef struct Node
{
	QElemType data;
	struct Node *next;
}QNode,*QueuePtr;

typedef struct
{
	QueuePtr front,rear;
}LinkQueue;

入列 出列

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 入列
Status EnQueue (LinkQueue *Q, QElemType e)
{
	QueuePtr s = (QueuePtr) malloc (sizeof(Node));
	if(!s)
		exit(0);
	s->data = e;
	s->next = NULL;
	Q->rear->next = s;
	Q->rear = s;
	return 0;
}

// 出列
Status DeQueue(LinkQueue *Q, QElemType *e)
{
	QueuePtr p;
	if (Q->front == Q->rear)
		return -1;
	p = Q->front->next;
	*e = p->data;
	Q->front->next = p->next;

	if(Q->rear = p)
		Q->rear = Q->free;
	free(p);
	return 0;
}
Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy