严蔚敏-栈和队列-栈的顺序实现和链式实现-队列的顺序实现和链式实现

数据结构学习笔记【第3章 栈和队列】

3.1 栈

3.1.1 抽象数据类型栈的定义

  • 栈是限定仅在表尾进行插入或删除操作的线性表。
  • 栈顶(top),栈底(bottom)。
  • 入栈:top++;出栈:top–。
  • 后进先出结构(简称LIFO结构)。

3.1.2 栈的表示和实现

  • 栈也有顺序和链式两种存储表示方法。
    栈的顺序存储表示和实现
#include<stdio.h>
#include<stdlib.h>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2

typedef int Status;
typedef int SElemType;

#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10

typedef struct {
	SElemType* base;
	SElemType* top;
	int stacksize;
}SqStack;

Status InitStack(SqStack& S);
Status DestroyStack(SqStack& S);
Status ClearStack(SqStack& S);
Status StackEmpty(SqStack& S);
int StackLength(SqStack S);
Status GetTop(SqStack S, SElemType& e);
Status Push(SqStack& S, SElemType e);
Status Pop(SqStack& S, SElemType& e);
void print_SqStack(SqStack S);

int main()
{
	SqStack S;
	InitStack(S);
	SElemType e;
	Push(S, 3);
	Push(S, 2);
	Push(S, 4);
	print_SqStack(S);
	Pop(S, e);
	print_SqStack(S);
	system("pause");
	return 0;
}
Status InitStack(SqStack& S)
{
	S.base = (SElemType*)malloc(STACK_INIT_SIZE * sizeof(SElemType));
	if (!S.base) exit(OVERFLOW);
	S.top = S.base;
	S.stacksize = STACK_INIT_SIZE;
	return OK;
}
Status DestroyStack(SqStack& S)
{
	free(&S);
	return OK;
}
Status ClearStack(SqStack& S)
{
	S.top = S.base;
	return OK;
}
Status StackEmpty(SqStack& S)
{
	if (S.top == S.base) return TRUE;
	return FALSE;
}
int StackLength(SqStack S)
{
	if (S.base > S.top)return INFEASIBLE;
	return (S.top - S.base);
}
Status GetTop(SqStack S, SElemType& e)
{
	if (S.top == S.base) return ERROR;
	e = *(S.top - 1);
	return OK;
}
Status Push(SqStack& S, SElemType e)
{
	if (S.top - S.base >= S.stacksize) {
		S.base = (SElemType*)realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(SElemType));
		if (!S.base) exit(OVERFLOW);
		S.top = S.base + S.stacksize;
		S.stacksize += STACKINCREMENT;
	}
	*S.top++ = e;
}
Status Pop(SqStack& S, SElemType& e)
{
	if (S.top == S.base) return ERROR;
	e = *--S.top;
	return OK;
}
void print_SqStack(SqStack S)
{
	SElemType* p;
	p = S.base;
	printf("S(length:%d):",StackLength(S));
	while (p < S.top)
	{
		printf("%d ",*p);
		p++;
	}
	printf("\n");
}

3.2 栈的应用举例

3.2.1 数制转换

  • 利用栈的后入先出结构
  • 对于输入的任意一个非负十进制整数,打印输出与其等值的八进制数
void conversion()
{
	//对于输入的任意一个非负十进制整数,打印输出与其等值的八进制数
	SqStack S;
	InitStack(S);
	int N;
	printf("Please input the N:");
	scanf_s("%d", &N);
	while (N)
	{
		Push(S, N % 8);
		N = N / 8;
	}
	print_SqStack(S);
	while (!StackEmpty(S))
	{
		int e;
		Pop(S, e);
		printf("%d", e);
	}
}

3.2.2 括号匹配的检验

  • [ ( [ ] [ ] ) ] [ ( [ ] [ ] ) ]
  • 1 2 3 4 5 6 7 8 (与上述括号对应)
  • 旨在解决括号不匹配问题
  • 每增加一个左括号,便将其入栈作为迫切期待(即期待与其匹配的右括号出现)
  • 每增加一个右括号,与其匹配的左括号得以消解
  • 括号具有优先性(即优先消解的权利),越是后出现的括号优先性越高,即后入先出结构

3.2.3 行编辑程序

  • 旨在解决用户输错问题(用户输入特殊字符达到撤销输入的目的),用‘#’表示撤销前一个字符,用‘@’表示撤销前面所有字符
  • 利用字符栈S,从终端接收一行并传送至调用过程的数据区。
void LineEdit()
{
	SqStack S;
	InitStack(S);
	char ch = getchar();
	getchar();
	while (ch != '.') {
		while (ch != '.' && ch != '\n') {
			switch (ch)
			{
			case'#':
				char c;
				Pop(S, c);
				break;
			case'@':
				ClearStack(S);
				break;
			default:
				Push(S, ch);
				break;
			}
			ch = getchar();
			getchar();
		}
		print_SqStack(S);
		ClearStack(S);
		if (ch != '.') ch = getchar();
	}
	DestroyStack(S);
}

3.2.4 迷宫求解

  • 为保证在任何位置上都能沿原路返回,需要用一个后入先出的结构来保存从入口到当前位置的路径
  • 迷宫用方块图表示; 可通:未曾走到过的通道块
  • 基本思想:
    若当前位置可通则纳入当前路径(入栈);若当前位置不可通则应逆向退到前一通道块,并向其他方向继续探索;若该通道块各个方向均不可通,则应从当前路径上删除该通道块(出栈)。

3.2.5 表达式求值

  • 把一个表达式翻译成正确求值的一个机器指令序列
  • 算符优先法
  • 算法思想:
    使用两个工作栈。一个叫OPTR用于寄存运算符;另一个叫OPND,用于寄存操作数或运算结果。
    (1)首先置操作数栈为空栈,表达式起始符”#“为运算符栈的栈底元素;
    (2)依次读入表达式中每个字符,若是操作数则进OPND栈,若是运算符则和OPTR栈的栈顶元素比较优先权后作相应操作,直至整个表达式求值完毕(即OPTR栈的栈顶元素和当前读入的字符均为”#“)。 (“#“标志表达式的首尾)

3.3 栈与递归的实现

  • 未完待续…

3.4 队列

3.4.1 抽象数据类型队列的定义

  • 先进先出结构(FIFO)
  • 允许在一端插入元素(队尾)一端删除元素(队头),类似排队

3.4.2 链队列——队列的链式表示实现

#include<stdio.h>
#include<stdlib.h>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2

typedef int Status;
typedef int QElemType;

typedef struct QNode {
	QElemType data;
	struct QNode* next;
}QNode, * QueuePtr;

typedef struct {
	QueuePtr front;
	QueuePtr rear;
}LinkQueue;

Status InitQueue(LinkQueue& Q);
//构造一个空队列Q
Status DestroyQueue(LinkQueue& Q);
//销毁队列Q,Q不再存在
Status ClearQueue(LinkQueue& Q);
//将Q清为空队列
Status QueueEmpty(LinkQueue Q);
//若队列Q为空队列,则返回TRUE,反之,返回FALSE
int QueueLength(LinkQueue Q);
//返回Q的元素个数,即队列的长度
Status GetHead(LinkQueue Q, QElemType& e);
//若队列不空,则用e返回Q的队头元素,并返回OK;否则返回ERROR
Status EnQueue(LinkQueue& Q, QElemType e);
//插入元素e为Q的新的队尾元素
Status DeQueue(LinkQueue& Q, QElemType& e);
//删除队尾元素
void print_Queue(LinkQueue Q);

int main()
{
	LinkQueue Q;
	InitQueue(Q);
	print_Queue(Q);
	EnQueue(Q, 1);
	EnQueue(Q, 2);
	EnQueue(Q, 3);
	EnQueue(Q, 4);
	EnQueue(Q, 5);
	print_Queue(Q);
	QElemType e;
	DeQueue(Q, e);
	print_Queue(Q);
	system("pause");
	return 0;
}
Status InitQueue(LinkQueue& Q)
{
	Q.front = (QueuePtr)malloc(sizeof(QNode));
	if (!Q.front) exit(OVERFLOW);
	Q.rear = Q.front;
	Q.front->next = NULL;
	return OK;
}
Status DestroyQueue(LinkQueue& Q)
{
	while (Q.front) {
		Q.rear = Q.front->next;
		//free(Q.front);
		Q.front = Q.rear;
	}
	return OK;
}
Status ClearQueue(LinkQueue& Q)
{
	Q.front = Q.rear;
	return OK;
}
Status QueueEmpty(LinkQueue Q)
{
	if (Q.front == Q.rear)return TRUE;
	return FALSE;
}
int QueueLength(LinkQueue Q)
{
	QueuePtr p;
	p = (QueuePtr)malloc(sizeof(QNode));
	if (!p)exit(OVERFLOW);
	p = Q.front;
	int length = 0;
	while (p <= Q.rear) {
		p = p->next;
		if (!p)break;
		length++;
	}
	return length;
}
Status GetHead(LinkQueue Q, QElemType& e)
{
	if (!QueueEmpty(Q)) {
		e = Q.front->data;
		return OK;
	}
	return ERROR;
}
Status EnQueue(LinkQueue& Q, QElemType e)
{
	QueuePtr p;
	p = (QueuePtr)malloc(sizeof(QNode));
	if (!p)exit(OVERFLOW);
	p->data = e;
	p->next = NULL;
	Q.rear->next = p;
	Q.rear = p;
	return OK;
}
Status DeQueue(LinkQueue& Q, QElemType& e)
{
	if (QueueEmpty(Q))return ERROR;
	QueuePtr p;
	p = (QueuePtr)malloc(sizeof(QNode));
	if (!p)exit(OVERFLOW);
	p = Q.front->next;
	e = p->data;
	Q.front->next = p->next;
	Q.front = p;
	if (Q.rear == p)Q.rear = Q.front;
	return OK;
}
void print_Queue(LinkQueue Q)
{
	if (Q.front == Q.rear) {
		printf("NULL\n");
		return;
	}
	QueuePtr p;
	p = (QueuePtr)malloc(sizeof(QNode));
	if (!p)exit(OVERFLOW);
	p = Q.front->next;
	printf("Q(length:%d):",QueueLength(Q));
	while (p <= Q.rear) {
		printf("%d ", p->data);
		p = p->next;
		if (!p)break;
	}
	printf("\n");
}

3.4.3 循环队列——队列的顺序表示和实现

  • 鉴于队列的先入先出结构,不宜用数组表示;一个巧妙的方法是将顺序队列臆造为一个环状空间。
  • Q.front==Q.rear,环状下,队列空和满都可满足,这是,不妨约定队列头指针在队列尾指针的下一位置上作为队列满的标志(即少用一个空间,Q.rear仅标志队尾不指向数据)。
#include<stdio.h>
#include<stdlib.h>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2

typedef int Status;
typedef int QElemType;

#define MAXQSIZE 100

typedef struct {
	QElemType* base;
	int front;
	int rear;
}SqQueue;

Status InitQueue(SqQueue& Q);
Status DestroyQueue(SqQueue& Q);
Status ClearQueue(SqQueue& Q);
Status QueueEmpty(SqQueue Q);
int QueueLength(SqQueue Q);
Status GetHead(SqQueue Q, QElemType& e);
Status EnQueue(SqQueue& Q, QElemType e);
//插入元素e为Q的新的队尾元素
Status DeQueue(SqQueue& Q, QElemType& e);
//删除队尾元素
void print_Queue(SqQueue Q);

int main()
{
	SqQueue(Q);
	InitQueue(Q);
	print_Queue(Q);
	EnQueue(Q, 1);
	EnQueue(Q, 2);
	EnQueue(Q, 3);
	EnQueue(Q, 4);
	EnQueue(Q, 5);
	print_Queue(Q);
	QElemType e;
	DeQueue(Q, e);
	print_Queue(Q);
	system("pause");
	return 0;
}
Status InitQueue(SqQueue& Q)
{
	Q.base = (QElemType*)malloc(MAXQSIZE * sizeof(QElemType));
	if (!Q.base) exit(OVERFLOW);
	Q.rear = 0;
	Q.front = Q.rear;
	return OK;
}
Status DestroyQueue(SqQueue& Q)
{
	while (Q.base) {
		Q.base = NULL;
	}
	return OK;
}
Status ClearQueue(SqQueue& Q)
{
	Q.rear = 0;
	Q.front = Q.rear;
	return OK;
}
Status QueueEmpty(SqQueue Q)
{
	if (Q.front == Q.rear)return TRUE;
	return FALSE;
}
int QueueLength(SqQueue Q)
{
	return(Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
}
Status GetHead(SqQueue Q, QElemType& e)
{
	if (Q.front == Q.rear) return ERROR;
	e = Q.base[Q.front];
	return OK;
}
Status EnQueue(SqQueue& Q, QElemType e)
{
	if ((Q.rear + 1) % MAXQSIZE == Q.front)return ERROR;
	Q.base[Q.rear] = e;
	Q.rear = (Q.rear + 1) % MAXQSIZE;
	return OK;
}
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;
}
void print_Queue(SqQueue Q)
{
	if (Q.front == Q.rear) {
		printf("NULL\n");
		return;
	}
	int i;
	printf("Q:");
	for (i = Q.front; i < Q.rear; i++)
	{
		printf("%d ", Q.base[i]);
	}
	printf("\n");
}

3.5 离散事件模拟

  • 旨在使用队列和线性表之类的数据结构解决排队情景下的问题
  • 未完待续…
发布了40 篇原创文章 · 获赞 12 · 访问量 5741

猜你喜欢

转载自blog.csdn.net/weixin_43488958/article/details/104099699