第三章 栈和队列--以下代码由C语言实现
王道学习
3.1 知识框架

3.2 栈
3.2.1 栈的基本概念
1.栈的定义
栈(Stack)是只允许在一端进行插入或删除操作的线性表。首先栈是一种线性表,但限定这种线性表只能在某一端进行插入和删除操作,如图3.1所示。

栈顶( Top)。线性表允许进行插入删除的那一端。
栈底(Bottom)。固定的,不允许进行插入和删除的另一端。
空栈。不含任何元素的空表。
假设某个栈S=(a1, a2, a3, a4, a5),如图3.1所示,则a1为栈底元素,a5为栈顶元素。由于栈只能在栈顶进行插入和删除操作,进栈次序依次为a1, a2, a3, a4, a5,而出栈次序为a5, a4, a3, a2, a1。由此可见,栈的操作特性可以明显地概括为后进先出(Last In First Out,LIFO)。

注意:我们每接触到一种新的数据结构类型,都应该分别从其逻辑结构,存储结构和对数据的运算三个方面着手,以加深对定义的理解。
2.栈的基本操作

3.2.2 栈的顺序存储结构
栈是一种操作受限的线性表,类似于线性表,它也有对应的两种存储方式。
第一种实现

//顺序栈--数组实现
#include <stdio.h>
#define MaxSize 10
struct SqStack{
int data[MaxSize];
int top;
};
typedef struct SqStack SqStack;
/*
初始化顺序栈
*/
void initStack(SqStack *sqStack){
(*sqStack).top=-1;
}
/*
销毁顺序栈
*/
void destory(SqStack *sqStack){
(*sqStack).top=-1;
}
/*
判空栈
返回值
0--空
1--非空
*/
int stackEmpty(SqStack *sqStack){
int top=(*sqStack).top;
if(top==-1){
return 0;
}
return 1;
}
/*
进栈
返回值
0--失败
1--成功
*/
int push(SqStack *sqStack,int data){
int top=(*sqStack).top;
if(top==MaxSize-1){
return 0;
}
(*sqStack).top=top+1;
(*sqStack).data[top+1]=data;
return 1;
}
/*
出栈
返回值
0--失败
1--成功
*/
int pop(SqStack *sqStack,int *data){
int top=(*sqStack).top;
if(top==-1){
return 0;
}
(*data)=(*sqStack).data[top];
(*sqStack).top=top-1;
return 1;
}
/*
读栈顶元素
返回值
0--失败
1--成功
*/
int getTop(SqStack *sqStack,int *data){
int top=(*sqStack).top;
if(top==-1){
return 0;
}
(*data)=(*sqStack).data[top];
return 1;
}
int main(){
SqStack sqStack;
initStack(&sqStack);
printf("%d",sqStack.top);
return 0;
}
#include <stdio.h>
#define MaxSize 10
struct SqStack{
int data[MaxSize];
int top;
};
typedef struct SqStack SqStack;
void initStack(SqStack *sqStack){
sqStack->top=-1;
}
void destory(SqStack *sqStack){
sqStack->top=-1;
}
int stackEmpty(SqStack *sqStack){
int top=sqStack->top;
if(top==01){
return 0;
}
return 1;
}
int push(SqStack *sqStack,int data){
int top=sqStack->top;
if(top==MaxSize-1){
return 0;
}
sqStack->top=top+1;
sqStack->data[top+1]=data;
return 1;
}
int pop(SqStack *sqStack,int *data){
int top=sqStack->top;
if(top==-1){
return 0;
}
*data=sqStack->data[top];
sqStack->top=top-1;
return 1;
}
int getTop(SqStack *sqStack,int *data){
int top=sqStack->top;
if(top==-1){
return 0;
}
*data=sqStack->data[top];
return 1;
}
int main(){
SqStack sqStack;
initStack(&sqStack);
printf("%d",sqStack.top);
return 0;
}
第二种实现

//顺序栈--数组实现
#include <stdio.h>
#define MaxSize 10
struct SqStack{
int data[MaxSize];
int top;
};
typedef struct SqStack SqStack;
/*
初始化顺序栈
*/
void initStack(SqStack *sqStack){
(*sqStack).top=0;
}
/*
销毁顺序栈
*/
void destory(SqStack *sqStack){
(*sqStack).top=0;
}
/*
判空栈
返回值
0--空
1--非空
*/
int stackEmpty(SqStack *sqStack){
int top=(*sqStack).top;
if(top==0){
return 0;
}
return 1;
}
/*
进栈
返回值
0--失败
1--成功
*/
int push(SqStack *sqStack,int data){
int top=(*sqStack).top;
if(top==MaxSize){
return 0;
}
(*sqStack).data[top]=data;
(*sqStack).top=top+1;
return 1;
}
/*
出栈
返回值
0--失败
1--成功
*/
int pop(SqStack *sqStack,int *data){
int top=(*sqStack).top;
if(top==0){
return 0;
}
(*sqStack).top=top-1;
(*data)=(*sqStack).data[top];
return 1;
}
/*
读栈顶元素
返回值
0--失败
1--成功
*/
int getTop(SqStack *sqStack,int *data){
int top=(*sqStack).top;
if(top==0){
return 0;
}
top=top-1;
(*data)=(*sqStack).data[top];
return 1;
}
int main(){
SqStack sqStack;
initStack(&sqStack);
printf("%d",sqStack.top);
return 0;
}
#include <stdio.h>
#define MaxSize 10
struct SqStack{
int data[MaxSize];
int top;
};
typedef struct SqStack SqStack;
void initStack(SqStack *sqStack){
sqStack->top=0;
}
void destory(SqStack *sqStack){
sqStack->top=0;
}
int stackEmpty(SqStack *sqStack){
int top=sqStack->top;
if(top==0){
return 0;
}
return 1;
}
int push(SqStack *sqStack,int data){
int top=(*sqStack).top;
if(top==MaxSize){
return 0;
}
sqStack->data[top]=data;
sqStack->top=top+1;
return 1;
}
int pop(SqStack *sqStack,int *data){
int top=(*sqStack).top;
if(top==0){
return 0;
}
sqStack->top=top-1;
*data=sqStack->data[top];
return 1;
}
int getTop(SqStack *sqStack,int *data){
int top=(*sqStack).top;
if(top==0){
return 0;
}
top=top-1;
*data=sqStack->data[top];
return 1;
}
int main(){
SqStack sqStack;
initStack(&sqStack);
printf("%d",sqStack.top);
return 0;
}
共享栈



3.2.3 栈的链式存储结构
采用链式存储,便于结点的插入与删除。链栈的操作与链表类似,入栈和出栈的操作都在链表的表头进行。需要注意的是,对于带头结点和不带头结点的链栈,具体的实现会有所不同。
带头结点
//栈的链式存储--带头结点
#include <stdio.h>
#include <stdlib.h>
struct LNode{
int data;
struct LNode *next;
};
typedef struct LNode LNode;
typedef struct LNode* SqStack;
/*
初始化链式栈:
1、头指针指向头结点
2、头结点的next初始化为NULL
返回一个SqStack型变量:
具体的值--成功
NULL--失败
*/
SqStack initStack(SqStack sqStack){
LNode* newLNode=(LNode*)malloc(sizeof(LNode));
if(newLNode==NULL){
return NULL;
}
(*newLNode).next=NULL;
sqStack=newLNode;
return sqStack;
}
/*
销毁链式栈
*/
void destory(SqStack sqStack){
while(sqStack!=NULL){
LNode* tmpLNode=sqStack;
sqStack=(*sqStack).next;
free(tmpLNode);
}
}
/*
判空栈
返回值
0--空
1--非空
*/
int stackEmpty(SqStack sqStack){
if(sqStack==NULL){
return 0;
}
if((*sqStack).next!=NULL){
return 1;
}else{
return 0;
}
}
/*
进栈
返回值
0--失败
1--成功
*/
int push(SqStack sqStack,int data){
//指向头结点
LNode *tmp=sqStack;
if(tmp==NULL){
return 0;
}
LNode *newLNode=(LNode *)malloc(sizeof(LNode));
if(newLNode==NULL){
return 0;
}
(*newLNode).data=data;
(*newLNode).next=(*tmp).next;
(*tmp).next=newLNode;
return 1;
}
/*
出栈
返回值
0--失败
1--成功
*/
int pop(SqStack sqStack,int *data){
//指向头结点
LNode *tmp=sqStack;
if(tmp==NULL){
return 0;
}
//指向第一个结点
LNode *p=(*tmp).next;
if(p==NULL){
return 0;
}
*data=(*p).data;
(*tmp).next=(*p).next;
free(p);
return 1;
}
/*
读栈顶元素
返回值
0--失败
1--成功
*/
int getTop(SqStack sqStack,int *data){
//指向头结点
LNode *tmp=sqStack;
if(tmp==NULL){
return 0;
}
//指向第一个结点
LNode *p=(*tmp).next;
if(p==NULL){
return 0;
}
*data=(*p).data;
return 1;
}
int main(){
SqStack sqStack;
return 0;
}
#include <stdio.h>
#include <stdlib.h>
struct LNode{
int data;
struct LNode *next;
};
typedef struct LNode LNode;
typedef struct LNode* SqStack;
SqStack initStack(SqStack sqStack){
LNode* newNode=(LNode*)malloc(sizeof(LNode));
if(newNode==NULL){
return NULL;
}
newNode->next=NULL;
sqStack=newNode;
return sqStack;
}
void destory(SqStack sqStack){
while(sqStack!=NULL){
LNode *tmpLNode=sqStack;
sqStack=sqStack->next;
free(tmpLNode);
}
}
int stackEmpty(SqStack sqStack){
if(sqStack==NULL){
return 0;
}
if(sqStack->next!=NULL){
return 1;
}else{
return 0;
}
}
int push(SqStack sqStack,int data){
LNode *tmp=sqStack;
if(tmp==NULL){
return 0;
}
LNode *newLNode=(LNode *)malloc(sizeof(LNode));
if(newLNode==NULL){
return 0;
}
newLNode->data=data;
newLNode->next=tmp->next;
tmp->next=newLNode;
return 1;
}
int pop(SqStack sqStack,int *data){
LNode *tmp=sqStack;
if(tmp==NULL){
return 0;
}
LNode *p=tmp->next;
if(p==NULL){
return 0;
}
*data=p->data;
tmp->next=p->next;
free(p);
return 1;
}
int getTop(SqStack sqStack,int *data){
LNode *tmp=sqStack;
if(tmp==NULL){
return 0;
}
LNode *p=tmp->next;
if(p==NULL){
return 0;
}
*data=p->data;
free(p);
return 1;
}
int main(){
return 0;
}
不带头结点
//栈的链式存储--不带头结点
#include <stdio.h>
#include <stdlib.h>
struct LNode{
int data;
struct LNode *next;
};
typedef struct LNode LNode;
typedef struct LNode* SqStack;
/*
初始化链式栈
*/
SqStack initStack(SqStack sqStack){
sqStack=NULL;
return sqStack;
}
/*
销毁链式栈
*/
void destory(SqStack sqStack){
while(sqStack!=NULL){
LNode* tmpLNode=sqStack;
sqStack=(*sqStack).next;
free(tmpLNode);
}
}
/*
判空栈
返回值
0--空
1--非空
*/
int stackEmpty(SqStack sqStack){
if(sqStack==NULL){
return 0;
}else{
return 1;
}
}
/*
进栈
返回值
NULL--失败
具体的地址--成功
*/
SqStack push(SqStack sqStack,int data){
LNode *newLNode=(LNode *)malloc(sizeof(LNode));
if(newLNode==NULL){
return NULL;
}
(*newLNode).data=data;
(*newLNode).next=sqStack;
sqStack=newLNode;
return sqStack;
}
/*
出栈
返回值
NULL--失败
具体的地址--成功
*/
SqStack pop(SqStack sqStack,int *data){
//指向第一个结点
LNode *tmp=sqStack;
if(tmp==NULL){
return NULL;
}
*data=(*tmp).data;
sqStack=(*tmp).next;
free(tmp);
return sqStack;
}
/*
读栈顶元素
返回值
0--失败
1--成功
*/
int getTop(SqStack sqStack,int *data){
//指向第一个结点
LNode *tmp=sqStack;
if(tmp==NULL){
return 0;
}
*data=(*tmp).data;
return 1;
}
int main(){
SqStack sqStack;
return 0;
}
#include <stdio.h>
#include <stdlib.h>
struct LNode{
int data;
struct LNode *next;
};
typedef struct LNode LNode;
typedef struct LNode* SqStack;
SqStack initStack(SqStack sqStack){
sqStack=NULL;
return sqStack;
}
void destory(SqStack sqStack){
while(sqStack!=NULL){
LNode *tmpLNode=sqStack;
sqStack=sqStack->next;
free(tmpLNode);
}
}
int stackEmpty(SqStack sqStack){
if(sqStack==NULL){
return 0;
}else{
return 1;
}
}
SqStack push(SqStack sqStack,int data){
LNode *newLNode=(LNode *)malloc(sizeof(LNode));
if(newLNode==NULL){
return NULL;
}
newLNode->data=data;
newLNode->next=sqStack;
sqStack=newLNode;
return sqStack;
}
int pop(SqStack sqStack,int *data){
LNode *tmp=sqStack;
if(tmp==NULL){
return 0;
}
*data=tmp->data;
sqStack=tmp->next;
free(tmp);
return 1;
}
int getTop(SqStack sqStack,int *data){
LNode *tmp=sqStack;
if(tmp==NULL){
return 0;
}
*data=tmp->data;
return 1;
}
int main(){
return 0;
}
3.2.4 本节试题精选
11、3个不同元素依次进栈,能得到()种不同的出栈序列。
A.4
B.5
C.6
D.7

A是排列
C是组合
https://www.bilibili.com/video/BV1Yq4y1E7JF/




3.3 队列
3.3.1 队列的基本概念
1.队列的定义

对头(Front)。允许删除的一端,又称队首。
对尾(Rear)。允许插入的一端。
空队列。不含任何元素的空表。
2.队列常见的基本操作
InitQueue(&Q):初始化队列,构造一个空队列Q。
QueueEmpty(Q):判队列空,若队列Q为空返回true,否则返回false。
EnQueue(&Q,x):入队,若队列Q未满,将x加入,使之成为新的队尾,
DeQueue(&Q,&x):出队,若队列Q非空,删除队头元素,并用x返回。
GetHead(Q,&x):读队头元素,若队列Q非空,则将队头元素赋值给x。
需要注意的是,栈和队列是操作受限的线性表,因此不是任何对线性表的操作都可以作为栈和队列的操作。比如,不可以随便读取栈或队列中间的某个数据。
3.3.2 队列的顺序存储结构
1.队列的顺序存储


2.循环队列
前面已指出了顺序队列的缺点,这里引出循环队列的概念。将顺序队列臆造为一个环状的空间,即把存储队列元素的表从逻辑上视为一个环,称为循环队列。当队首指针Q.front=MaxSize-1后,再前进一个位置就自动到0,这可以利用除法取余运算(%)来实现。
初始时:Q.front=Q.rear=0。
队首指针进1:Q.front= (Q.front+1)%MaxSize。
队尾指针进1:Q.rear=(Q.rear+1) %MaxSize。
队列长度:(Q.rear+MaxSize-Q.front) %MaxSize。
出队入队时:指针都按顺时针方向进1(如图3.7所示)。
那么,循环队列队空和队满的判断条件是什么呢?显然,队空的条件是Q.front= =Q.rearo若入队元素的速度快于出队元素的速度,则队尾指针很快就会赶上队首指针。如图3.7(d1)所示,此时可以看出队满时也有Q.front= =Q.rear。循环队列出入队示意图如图3.7所示。
为了区分队空还是队满的情况,有三种处理方式:




2.循环队列图解



判断队列已满/已空方法





3.3.2.1 第一种方式
//队列的顺序存储结构--判断队列已满使用(rear+1)%MaxSize==front
#include <stdio.h>
#define MaxSize 10
struct SqQueue{
int data[MaxSize];
int front;
int rear;
};
typedef struct SqQueue SqQueue;
/*
初始化队列
*/
void initQueue(SqQueue *queue){
(*queue).front=0;
(*queue).rear=0;
}
/*
判断队列是否为空
1--为空
0--不为空
*/
int queueEmpty(SqQueue queue){
if(queue.front==queue.rear){
return 1;
}else{
return 0;
}
}
/*
销毁队列
*/
void destoryQueue(SqQueue *queue){
(*queue).front=0;
(*queue).rear=0;
}
/*
入队操作
返回值
0--失败
1--成功
*/
int enQueue(SqQueue *queue,int data){
int front=(*queue).front;
int rear=(*queue).rear;
//判断队列是否已满
if((rear+1)%MaxSize==front){
return 0;
}
(*queue).data[rear]=data;
(*queue).rear=(rear+1)%MaxSize;
return 1;
}
/*
出队操作
返回值
0--失败
1--成功
*/
int deQueue(SqQueue *queue,int *data){
int front=(*queue).front;
int rear=(*queue).rear;
//判断队列是否已空
if(front==rear){
return 0;
}
*data=(*queue).data[front];
(*queue).front=(front+1)%MaxSize;
return 1;
}
/*
读队头元素操作
返回值
0--失败
1--成功
*/
int getHead(SqQueue *queue,int *data){
int front=(*queue).front;
int rear=(*queue).rear;
//判断队列是否已空
if(front==rear){
return 0;
}
*data=(*queue).data[front];
return 1;
}
int main(){
return 0;
}
#include <stdio.h>
#define MaxSize 10
struct SqQueue{
int data[MaxSize];
int front;
int rear;
};
typedef struct SqQueue SqQueue;
void initQueue(SqQueue *queue){
queue->front=0;
queue->rear=0;
}
int queueEmpty(SqQueue queue){
if(queue.front==queue.rear){
return 1;
}else{
return 0;
}
}
void destoryQueue(SqQueue *queue){
queue->front=0;
queue->rear=0;
}
int enQueue(SqQueue *queue,int data){
int front=queue->front;
int rear=queue->rear;
if((rear+1)%MaxSize==front){
return 0;
}
queue->data[rear]=data;
queue->rear=(rear+1)%MaxSize;
return 1;
}
int deQueue(SqQueue *queue,int *data){
int front=queue->front;
int rear=queue->rear;
if(front==rear){
return 0;
}
*data=queue->data[front];
queue->front=(front+1)%MaxSize;
return 1;
}
int getHead(SqQueue *queue,int *data){
int front=queue->front;
int rear=queue->rear;
if(front==rear){
return 0;
}
*data=queue->data[front];
return 1;
}
int main(){
return 0;
}
3.3.2.2 第二种方式
/*
队列的顺序存储结构
判断队列已满使用size变量
*/
#include <stdio.h>
#define MaxSize 10
struct SqQueue{
int data[MaxSize];
int front;
int rear;
int size;
};
typedef struct SqQueue SqQueue;
/*
初始化队列
*/
void initQueue(SqQueue *queue){
(*queue).front=0;
(*queue).rear=0;
(*queue).size=0;
}
/*
判断队列是否为空
1--为空
0--不为空
*/
int queueEmpty(SqQueue queue){
if(size==0){
return 1;
}else{
return 0;
}
}
/*
销毁队列
*/
void destoryQueue(SqQueue *queue){
(*queue).size=0;
}
/*
入队操作
返回值
0--失败
1--成功
*/
int enQueue(SqQueue *queue,int data){
int size=(*queue).size;
int rear=(*queue).rear;
//判断队列是否已满
if(size==MaxSize){
return 0;
}
(*queue).data[rear]=data;
(*queue).rear=(rear+1)%MaxSize;
(*queue).size=size+1;
return 1;
}
/*
出队操作
返回值
0--失败
1--成功
*/
int deQueue(SqQueue *queue,int *data){
int size=(*queue).size;
int front=(*queue).front;
//判断队列是否已空
if(size==0){
return 0;
}
*data=(*queue).data[front];
(*queue).front=(front+1)%MaxSize;
(*queue).size=size-1;
return 1;
}
/*
读队头元素操作
返回值
0--失败
1--成功
*/
int getHead(SqQueue *queue,int *data){
int size=(*queue).size;
int front=(*queue).front;
//判断队列是否已空
if(size==0){
return 0;
}
*data=(*queue).data[front];
return 1;
}
int main(){
return 0;
}
#include <stdio.h>
#define MaxSize 10
struct SqQueue{
int data[MaxSize];
int front;
int rear;
int size;
};
typedef struct SqQueue SqQueue;
void initQueue(SqQueue *queue){
queue->front=0;
queue->rear=0;
queue->size=0;
}
int queueEmpty(SqQueue queue){
if(queue.size==0){
return 1;
}else{
return 0;
}
}
void destoryQueue(SqQueue *queue){
queue->size==0;
}
int enQueue(SqQueue *queue,int data){
int size=queue->size;
int rear=queue->rear;
if(size==MaxSize){
return 0;
}
queue->data[rear]=data;
queue->rear=(rear+1)%MaxSize;
queue->size=size+1;
return 1;
}
int deQueue(SqQueue *queue,int *data){
int size=queue->size;
int front=queue->front;
if(size==0){
return 0;
}
*data=queue->data[front];
queue->front=(front+1)%MaxSize;
queue->size=size-1;
return 1;
}
int getHead(SqQueue *queue,int *data){
int size=queue->size;
int front=queue->front;
if(size==0){
return 0;
}
*data=queue->data[front];
return 1;
}
int main(){
return 0;
}
3.3.2.3 第三种方式
/*
队列的顺序存储结构
判断队列已满使用tag变量
*/
#include <stdio.h>
#define MaxSize 10
struct SqQueue{
int data[MaxSize];
int front;
int rear;
//最近进行的是0--删除 1--插入
int tag;
};
typedef struct SqQueue SqQueue;
/*
初始化队列
*/
void initQueue(SqQueue *queue){
(*queue).front=0;
(*queue).rear=0;
(*queue).tag=0;
}
/*
判断队列是否为空
1--为空
0--不为空
*/
int queueEmpty(SqQueue queue){
int front=queue.front;
int rear=queue.rear;
int tag=queue.tag;
if(front==rear&&tag==0){
return 1;
}else{
return 0;
}
}
/*
销毁队列
*/
void destoryQueue(SqQueue *queue){
(*queue).front=0;
(*queue).rear=0;
(*queue).tag=0;
}
/*
入队操作
返回值
0--失败
1--成功
*/
int enQueue(SqQueue *queue,int data){
int front=(*queue).front;
int rear=(*queue).rear;
int tag=(*queue).tag;
//判断队列是否已满
if(front==rear&&tag==1){
return 0;
}
(*queue).data[rear]=data;
(*queue).rear=(rear+1)%MaxSize;
(*queue).tag=1;
return 1;
}
/*
出队操作
返回值
0--失败
1--成功
*/
int deQueue(SqQueue *queue,int *data){
int front=(*queue).front;
int rear=(*queue).rear;
int tag=(*queue).tag;
//判断队列是否已空
if(front==rear&&tag==0){
return 0;
}
*data=(*queue).data[front];
(*queue).front=(front+1)%MaxSize;
(*queue).tag=0;
return 1;
}
/*
读队头元素操作
返回值
0--失败
1--成功
*/
int getHead(SqQueue *queue,int *data){
int front=(*queue).front;
int rear=(*queue).rear;
int tag=(*queue).tag;
//判断队列是否已空
if(ront==rear&&tag==0){
return 0;
}
*data=(*queue).data[front];
return 1;
}
int main(){
return 0;
}
#include <stdio.h>
#define MaxSize 10
struct SqQueue{
int data[MaxSize];
int front;
int rear;
int tag;
};
typedef struct SqQueue SqQueue;
void initQueue(SqQueue *queue){
queue->front=0;
queue->rear=0;
queue->tag=0;
}
int queueEmpty(SqQueue queue){
int front=queue.front;
int rear=queue.rear;
int tag=queue.tag;
if(front==rear&&tag==0){
return 1;
}else{
return 0;
}
}
void destoryQueue(SqQueue *queue){
queue->front=0;
queue->rear=0;
queue->tag=0;
}
int enQueue(SqQueue *queue,int data){
int front=queue->front;
int rear=queue->rear;
int tag=queue->tag;
if(front==rear&&tag==1){
return 0;
}
queue->data[rear]=data;
queue->rear=(rear+1)%MaxSize;
queue->tag=1;
return 1;
}
int deQueue(SqQueue *queue,int *data){
int front=queue->front;
int rear=queue->rear;
int tag=queue->tag;
if(front==rear&&tag==0){
return 0;
}
*data=queue->data[front];
queue->front=(front+1)%MaxSize;
queue->tag=0;
return 1;
}
int getHead(SqQueue *queue,int *data){
int front=queue->front;
int rear=queue->rear;
int tag=queue->tag;
if(front==rear&&tag==0){
return 0;
}
*data=queue->data[front];
return 1;
}
int main(){
return 0;
}
3.3.3 队列的链式存储

3.3.3.1 带头结点



//队列的链式存储--带头结点
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 10
struct LinkNode{
int data;
struct LinkNode *next;
};
typedef struct LinkNode LinkNode;
struct LinkQueue{
LinkNode *front;
LinkNode *rear;
};
typedef struct LinkQueue LinkQueue;
/*
初始化队列
返回值
0--失败
1--成功
*/
int initQueue(LinkQueue *queue){
LinkNode *newNode=(LinkNode *)malloc(sizeof(LinkNode));
if(newNode==NULL){
return 0;
}
(*newNode).next=NULL;
(*queue).front=newNode;
(*queue).rear=newNode;
}
/*
判断队列是否为空
1--为空
0--不为空
*/
int queueEmpty(LinkQueue queue){
if(queue.front==queue.rear){
return 1;
}else{
return 0;
}
}
/*
销毁队列
*/
void destoryQueue(LinkQueue queue){
LinkNode *tmpNode=queue.front;
while(tmpNode!=NULL){
LinkNode *p=tmpNode;
tmpNode=(*tmpNode).next;
free(p);
}
}
/*
入队操作
返回值
0--失败
1--成功
*/
int enQueue(LinkQueue *queue,int data){
LinkNode *newNode=(LinkNode *)malloc(sizeof(LinkNode));
if(newNode==NULL){
return 0;
}
(*newNode).data=data;
(*newNode).next=NULL;
(*queue).rear->next=newNode;
(*queue).rear=newNode;
return 1;
}
/*
出队操作
返回值
0--失败
1--成功
*/
int deQueue(LinkQueue *queue,int *data){
LinkNode *front=(*queue).front;
LinkNode *rear=(*queue).rear;
//判断队列是否已空
if(front==rear){
return 0;
}
//被出队的结点--头结点的下一个结点
LinkNode *tmpNode=(*front).next;
*data=(*tmpNode).data;
(*front).next=(*tmpNode).next;
if((*tmpNode).next==NULL){
(*queue).rear=front;
}
free(tmpNode);
return 1;
}
/*
读队头元素操作
返回值
0--失败
1--成功
*/
int getHead(LinkQueue *queue,int *data){
LinkNode *front=(*queue).front;
LinkNode *rear=(*queue).rear;
//判断队列是否已空
if(front==rear){
return 0;
}
//被出队的结点--头结点的下一个结点
LinkNode *tmpNode=(*front).next;
*data=(*tmpNode).data;
return 1;
}
int main(){
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 10
struct LinkNode{
int data;
struct LinkNode *next;
};
typedef struct LinkNode LinkNode;
struct LinkQueue{
LinkNode *front;
LinkNode *rear;
};
typedef struct LinkQueue LinkQueue;
void initQueue(LinkQueue *queue){
LinkNode *newNode=(LinkNode *)malloc(sizeof(LinkNode));
if(newNode==NULL){
return 0;
}
(*newNode).next=NULL;
queue->front=newNode;
queue->rear=newNode;
}
int queueEmpty(LinkQueue queue){
if(queue.front==queue.rear){
return 1;
}else{
return 0;
}
}
void destoryQueue(LinkQueue queue){
LinkNode *tmpNode=queue.front;
while(tmpNode!=NULL){
LinkNode *p=tmpNode;
tmpNode=tmpNode->next;
free(p);
}
}
int enQueue(LinkQueue *queue,int data){
LinkNode *newNode=(LinkNode *)malloc(sizeof(LinkNode));
if(newNode==NULL){
return 0;
}
newNode->data=data;
newNode->next=NULL;
queue->rear->next=newNode;
queue->rear=newNode;
return 1;
}
int deQueue(LinkQueue *queue,int *data){
LinkNode *front=queue->front;
LinkNode *rear=queue->rear;
if(front==rear){
return 0;
}
LinkNode *tmpNode=front->next;
*data=tmpNode->data;
front->next=tmpNode->next;
if(tmpNode->next==NULL){
queue->rear=front;
}
free(tmpNode);
return 1;
}
int getHead(LinkQueue *queue,int *data){
LinkNode *front=queue->front;
LinkNode *rear=queue->rear;
if(front==rear){
return 0;
}
LinkNode *tmpNode=(*front).next;
*data=tmpNode->data;
return 1;
}
int main(){
return 0;
}
3.3.3.2 不带头结点



//队列的链式存储--不带头结点
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 10
struct LinkNode{
int data;
struct LinkNode *next;
};
typedef struct LinkNode LinkNode;
struct LinkQueue{
LinkNode *front;
LinkNode *rear;
};
typedef struct LinkQueue LinkQueue;
/*
初始化队列
返回值
0--失败
1--成功
*/
int initQueue(LinkQueue *queue){
(*queue).front=NULL;
(*queue).rear=NULL;
}
/*
判断队列是否为空
1--为空
0--不为空
*/
int queueEmpty(LinkQueue queue){
if(queue.front==NULL){
return 1;
}else{
return 0;
}
}
/*
销毁队列
*/
void destoryQueue(LinkQueue queue){
LinkNode *tmpNode=queue.front;
while(tmpNode!=NULL){
LinkNode *p=tmpNode;
tmpNode=(*tmpNode).next;
free(p);
}
}
/*
入队操作
返回值
0--失败
1--成功
*/
int enQueue(LinkQueue *queue,int data){
LinkNode *newNode=(LinkNode *)malloc(sizeof(LinkNode));
if(newNode==NULL){
return 0;
}
(*newNode).data=data;
(*newNode).next=NULL;
if((*queue).front==NULL){
(*queue).front=newNode;
(*queue).rear=newNode;
}else{
(*queue).rear->next=newNode;
(*queue).rear=newNode;
}
return 1;
}
/*
出队操作
返回值
0--失败
1--成功
*/
int deQueue(LinkQueue *queue,int *data){
LinkNode *front=(*queue).front;
LinkNode *rear=(*queue).rear;
//判断队列是否已空
if(front==NULL){
return 0;
}
//被出队的结点--头front指向的结点
LinkNode *tmpNode=front;
*data=(*tmpNode).data;
//如果front与rear指向同一个结点,说明队列只剩下一个结点
if(front==rear){
(*queue).front=NULL;
(*queue).rear=NULL;
}else{
(*queue).front=(*tmpNode).next;
}
free(tmpNode);
return 1;
}
/*
读队头元素操作
返回值
0--失败
1--成功
*/
int getHead(LinkQueue *queue,int *data){
LinkNode *front=(*queue).front;
//判断队列是否已空
if(front==NULL){
return 0;
}
//被出队的结点--头front指向的结点
LinkNode *tmpNode=front;
*data=(*tmpNode).data;
return 1;
}
int main(){
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 10
struct LinkNode{
int data;
struct LinkNode *next;
};
typedef struct LinkNode LinkNode;
struct LinkQueue{
LinkNode *front;
LinkNode *rear;
};
typedef struct LinkQueue LinkQueue;
void initQueue(LinkQueue *queue){
queue->front=NULL;
queue->rear=NULL;
}
int queueEmpty(LinkQueue queue){
if(queue.front==NULL){
return 1;
}else{
return 0;
}
}
void destoryQueue(LinkQueue queue){
LinkNode *tmpNode=queue.front;
while(tmpNode!=NULL){
LinkNode *p=tmpNode;
tmpNode=tmpNode->next;
free(p);
}
}
int enQueue(LinkQueue *queue,int data){
LinkNode *newNode=(LinkNode *)malloc(sizeof(LinkNode));
if(newNode==NULL){
return 0;
}
newNode->data=data;
newNode->next=NULL;
if(queue->front==NULL){
queue->front=newNode;
queue->rear=newNode;
}else{
queue->rear->next=newNode;
queue->rear=newNode;
}
return 1;
}
int deQueue(LinkQueue *queue,int *data){
LinkNode *front=queue->front;
LinkNode *rear=queue->rear;
if(front==NULL){
return 0;
}
LinkNode *tmpNode=front;
*data=tmpNode->data;
if(front==rear){
queue->front=NULL;
queue->rear=NULL;
}else{
queue->front=tmpNode->next;
}
free(tmpNode);
return 1;
}
int getHead(LinkQueue *queue,int *data){
LinkNode *front=queue->front;
if(front==NULL){
return 0;
}
LinkNode *tmpNode=front;
*data=tmpNode->data;
return 1;
}
int main(){
return 0;
}
3.3.4 双端队列






3.3.5 本节试题精选
8、【2011统考真题】已知循环队列存储在一维数组A [ 0..n-1]中,且队列非空时front和rear分别指向队头元素和队尾元素。若初始时队列为空,且要求第一个进入队列的元素存储在A[0]处,则初始时front和rear的值分别是()。
A. 0,0
B.0, n-1
C. n-1,0
D. n-1, n-1








3.4 栈和队列的应用
3.4.1 数制转换

//栈的链式存储--带头结点
#include <stdio.h>
#include <stdlib.h>
struct LNode{
int data;
struct LNode *next;
};
typedef struct LNode LNode;
typedef struct LNode* SqStack;
/*
初始化链式栈:
1、头指针指向头结点
2、头结点的next初始化为NULL
返回一个SqStack型变量:
具体的值--成功
NULL--失败
*/
SqStack initStack(SqStack sqStack){
LNode* newLNode=(LNode*)malloc(sizeof(LNode));
if(newLNode==NULL){
return NULL;
}
(*newLNode).next=NULL;
sqStack=newLNode;
return sqStack;
}
/*
销毁链式栈
*/
void destory(SqStack sqStack){
while(sqStack!=NULL){
LNode* tmpLNode=sqStack;
sqStack=(*sqStack).next;
free(tmpLNode);
}
}
/*
判空栈
返回值
0--空
1--非空
*/
int stackEmpty(SqStack sqStack){
if(sqStack==NULL){
return 0;
}
if((*sqStack).next!=NULL){
return 1;
}else{
return 0;
}
}
/*
进栈
返回值
0--失败
1--成功
*/
int push(SqStack sqStack,int data){
//指向头结点
LNode *tmp=sqStack;
if(tmp==NULL){
return 0;
}
LNode *newLNode=(LNode *)malloc(sizeof(LNode));
if(newLNode==NULL){
return 0;
}
(*newLNode).data=data;
(*newLNode).next=(*tmp).next;
(*tmp).next=newLNode;
return 1;
}
/*
出栈
返回值
0--失败
1--成功
*/
int pop(SqStack sqStack,int *data){
//指向头结点
LNode *tmp=sqStack;
if(tmp==NULL){
return 0;
}
//指向第一个结点
LNode *p=(*tmp).next;
if(p==NULL){
return 0;
}
*data=(*p).data;
(*tmp).next=(*p).next;
free(p);
return 1;
}
/*
读栈顶元素
返回值
0--失败
1--成功
*/
int getTop(SqStack sqStack,int *data){
//指向头结点
LNode *tmp=sqStack;
if(tmp==NULL){
return 0;
}
//指向第一个结点
LNode *p=(*tmp).next;
if(p==NULL){
return 0;
}
*data=(*p).data;
return 1;
}
int main(){
SqStack sqStack;
int number=1348;
int *data=&number;
sqStack=initStack(sqStack);
while(number!=0){
push(sqStack,number%8);
number=number/8;
}
while(stackEmpty(sqStack)!=0){
pop(sqStack,data);
printf("%d ",*data);
}
return 0;
}
3.4.1 栈在括号匹配中的应用

//栈--带头结点
#include <stdio.h>
#include <stdlib.h>
struct LNode{
char data;
struct LNode *next;
};
typedef struct LNode LNode;
typedef struct LNode* SqStack;
/*
初始化栈
*/
SqStack initList(SqStack sqStack){
//声明头结点
LNode *newLNode=(LNode*)malloc(sizeof(LNode));
(*newLNode).next=NULL;
sqStack=newLNode;
return sqStack;
}
/*
进栈
*/
void pushStack(SqStack sqStack,char data){
//头结点
LNode *headNode=sqStack;
//新结点
LNode *newLNode=(LNode*)malloc(sizeof(LNode));
(*newLNode).data=data;
(*newLNode).next=(*headNode).next;
(*headNode).next=newLNode;
}
/*
出栈
*/
int popStack(SqStack sqStack,char *data){
//指向头结点
LNode *headNode=sqStack;
if(headNode==NULL){
return 0;
}
//指向第一个结点
LNode *firstNode=(*headNode).next;
if(firstNode==NULL){
return 0;
}
*data=(*firstNode).data;
(*headNode).next=(*firstNode).next;
free(firstNode);
return 1;
}
/*
查看栈所有的元素
*/
void all(SqStack sqStack){
sqStack=(*sqStack).next;
printf("\n栈元素:");
while(sqStack!=NULL){
printf("%c ",(*sqStack).data);
sqStack=(*sqStack).next;
}
}
int main(){
SqStack sqStack;
char data='0';
char tmp='0';
sqStack=initList(sqStack);
while(data!='1'){
printf("\n\n请输入字符:");
scanf("%c",&data);
getchar();
if(data=='['||data=='('){
pushStack(sqStack,data);
all(sqStack);
}
if(data==']'){
if(popStack(sqStack,&tmp)==1){
if(tmp!='['){
printf("\n括号不匹配");
break;
}else{
printf("括号匹配,");
printf("匹配的括号:%c %c\n",tmp,data);
all(sqStack);
}
}else{
printf("\n括号不匹配");
break;
}
}
if(data==')'){
if(popStack(sqStack,&tmp)==1){
if(tmp!='('){
printf("\n括号不匹配");
break;
}else{
printf("括号匹配,");
printf("匹配的括号:%c %c\n",tmp,data);
all(sqStack);
}
}else{
printf("\n括号不匹配");
break;
}
}
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
struct LNode{
int data;
struct LNode *next;
};
typedef struct LNode LNode;
typedef struct LNode* SqStack;
SqStack initList(SqStack sqStack){
LNode *newNode=(LNode*)malloc(sizeof(LNode));
newNode->next=NULL;
sqStack=newNode;
return sqStack;
}
void pushStack(SqStack sqStack,char data){
LNode *newNode=(LNode*)malloc(sizeof(LNode));
newNode->data=data;
LNode *headNode=sqStack;
newNode->next=headNode->next;
headNode->next=newNode;
}
int popStack(SqStack sqStack,char *data){
LNode *headNode=sqStack;
if(headNode==NULL){
return 0;
}
if(headNode->next=NULL){
return 0;
}
LNode *firstNode=headNode->next;
*data=firstNode->data;
free(firstNode);
return 0;
}
void all(SqStack sqStack){
LNode *tmpNode=sqStack;
tmpNode=tmpNode->next;
printf("\n栈元素:");
while(tmpNode!=NULL){
printf("%c ",tmpNode->data);
tmpNode=tmpNode->next;
}
}
int main(){
SqStack sqStack;
char data='0';
char tmp='0';
sqStack=initList(sqStack);
while(data!='1'){
printf("\n\n请输入字符:");
scanf("%c",&data);
if(data=='['||data=='('){
pushStack(sqStack,data);
all(sqStack);
}
if(data==']'){
if(popStack(sqStack,&tmp)==1){
if(tmp!='['){
printf("\n括号不匹配");
break;
}else{
printf("括号匹配,");
printf("匹配的括号:%c %c\n",tmp,data);
all(sqStack);
}
}else{
printf("\n括号不匹配");
break;
}
}
if(data==')'){
if(popStack(sqStack,&tmp)==1){
if(tmp!='('){
printf("\n括号不匹配");
break;
}else{
printf("括号匹配,");
printf("匹配的括号:%c %c\n",tmp,data);
all(sqStack);
}
}else{
printf("\n括号不匹配");
break;
}
}
}
return 0;
}
3.4.2 栈在表达式求值中的应用
介绍














中缀转后缀(机算)





3.4.3 栈在递归中的应用


斐波那契数列的递归算法与非递归算法
非递归算法一
#include <stdio.h>
int fibOne(int num){
int i=0;
int array[num];
array[0]=0;
array[1]=1;
for(i=2;i<=num;i++){
array[i]=array[i-1]+array[i-2];
}
return array[num];
}
int main(){
printf("%d",fibOne(2));
return 0;
}
非递归算法二
#include <stdio.h>
int fibTwo(int num){
int first=0;
int second=1;
int third=0;
int i=0;
for(i=2;i<=num;i++){
third=first+second;
first=second;
second=third;
}
return third;
}
int main(){
printf("%d",fibTwo(2));
return 0;
}
3.4.4 车厢编组

//队列的链式存储--带头结点
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 10
struct LinkNode{
char data;
struct LinkNode *next;
};
typedef struct LinkNode LinkNode;
struct LinkQueue{
LinkNode *front;
LinkNode *rear;
};
typedef struct LinkQueue LinkQueue;
/*
初始化队列
返回值
0--失败
1--成功
*/
int initQueue(LinkQueue *queue){
LinkNode *newNode=(LinkNode *)malloc(sizeof(LinkNode));
if(newNode==NULL){
return 0;
}
(*newNode).next=NULL;
(*queue).front=newNode;
(*queue).rear=newNode;
}
/*
判断队列是否为空
1--为空
0--不为空
*/
int queueEmpty(LinkQueue queue){
if(queue.front==queue.rear){
return 1;
}else{
return 0;
}
}
/*
销毁队列
*/
void destoryQueue(LinkQueue queue){
LinkNode *tmpNode=queue.front;
while(tmpNode!=NULL){
LinkNode *p=tmpNode;
tmpNode=(*tmpNode).next;
free(p);
}
}
/*
入队操作
返回值
0--失败
1--成功
*/
int enQueue(LinkQueue *queue,char data){
LinkNode *newNode=(LinkNode *)malloc(sizeof(LinkNode));
if(newNode==NULL){
return 0;
}
(*newNode).data=data;
(*newNode).next=NULL;
(*queue).rear->next=newNode;
(*queue).rear=newNode;
return 1;
}
/*
出队操作
返回值
0--失败
1--成功
*/
int deQueue(LinkQueue *queue,char *data){
LinkNode *front=(*queue).front;
LinkNode *rear=(*queue).rear;
//判断队列是否已空
if(front==rear){
return 0;
}
//被出队的结点--头结点的下一个结点
LinkNode *tmpNode=(*front).next;
*data=(*tmpNode).data;
(*front).next=(*tmpNode).next;
if((*tmpNode).next==NULL){
(*queue).rear=front;
}
free(tmpNode);
return 1;
}
/*
读队头元素操作
返回值
0--失败
1--成功
*/
int getHead(LinkQueue *queue,int *data){
LinkNode *front=(*queue).front;
LinkNode *rear=(*queue).rear;
//判断队列是否已空
if(front==rear){
return 0;
}
//被出队的结点--头结点的下一个结点
LinkNode *tmpNode=(*front).next;
*data=(*tmpNode).data;
return 1;
}
int main(){
LinkQueue a;
LinkQueue b;
LinkQueue c;
char tempChar='A';
char *data=&tempChar;
initQueue(&a);
initQueue(&b);
initQueue(&c);
enQueue(&a,'H');
enQueue(&a,'S');
enQueue(&a,'H');
enQueue(&a,'S');
while(queueEmpty(a)!=1){
deQueue(&a,data);
if((*data)=='H'){
enQueue(&b,(*data));
}else{
enQueue(&c,(*data));
}
}
printf("-----------------------------\n");
while(queueEmpty(b)!=1){
deQueue(&b,data);
printf("%c ",(*data));
}
printf("\n");
printf("-----------------------------\n");
while(queueEmpty(c)!=1){
deQueue(&c,data);
printf("%c ",(*data));
}
return 0;
}
3.4.4 队列在层次遍历中的应用


3.4.5 队列在计算机系统中的应用
队列在计算机系统中的应用非常广泛,以下仅从两个方面来简述队列在计算机系统中的作用:第一个方面是解决主机与外部设备之间速度不匹配的问题,第二个方面是解决由多用户引起的资源竞争问题。
对于第一个方面,仅以主机和打印机之间速度不匹配的问题为例做简要说明。主机输出数据给打印机打印,输出数据的速度比打印数据的速度要快得多,由于速度不匹配,若直接把输出的数据送给打印机打印显然是不行的。解决的方法是设置一个打印数据缓冲区,主机把要打印输出的数据依次写入这个缓冲区,写满后就暂停输出,转去做其他的事情。打印机就从缓冲区中按照先进先出的原则依次取出数据并打印,打印完后再向主机发出请求。主机接到请求后再向缓冲区写入打印数据。这样做既保证了打印数据的正确,又使主机提高了效率。由此可见,打印数据缓冲区中所存储的数据就是一个队列。
对于第二个方面,CPU(即中央处理器,它包括运算器和控制器)资源的竞争就是一个典型的例子。在一个带有多终端的计算机系统上,有多个用户需要CPU各自运行自己的程序,它们分别通过各自的终端向操作系统提出占用CPU的请求。操作系统通常按照每个请求在时间上的先后顺序,把它们排成一个队列,每次把CPU分配给队首请求的用户使用。当相应的程序运行结束或用完规定的时间间隔后,食其出队,再把 CPU分配给新的队首请求的用户使用。这样既能满足每个用户的请求,又使CPU能够正常运行。


3.4.6 本节试题精选

3、下面()用到了队列。
A.括号匹配
B.迷宫求解
C.页面替换算法
D.递归
7、对于一个问题的递归算法求解和其相对应的非递归算法求解,()。
A.递归算法通常效率高一些
B.非递归算法通常效率高一些
C.两者相同
D.无法比较





10.A





3.5 矩阵的压缩存储
矩阵在计算机图形学、工程计算中占有举足轻重的地位。在数据结构中考虑的是如何用最小的内存空间来存储同样的一-组数据。所以,我们不研究矩阵及其运算等,而把精力放在如何将矩阵更有效地存储在内存中并能方便地提取矩阵中的元素。
3.5.1 数组的定义
数组是由n(n1)个相同类型的数据元素构成的有限序列,每个数据元素称为一个数组元素,每个元素在n个线性关系中的序号称为该元素的下标,下标的取值范围称为数组的维界。
数组与线性表的关系:数组是线性表的推广。一维数组可视为一个线性表;二维数组可视为其元素也是定长线性表的线性表,以此类推。数组一旦被定义,其维数和维界就不再改变。因此,除结构的初始化和销毁外,数组只会有存取元素和修改元素的操作。
补充:
数组(array)是一种线性表数据结构,它用一组连续的内存空间来存储一组具有相同类型的数据。
3.5.2 数组的存储结构




3.5.3 矩阵的压缩存储
1.对称矩阵







2.三角矩阵


3.三对角矩阵



3.5.4 稀疏矩阵


3.5.5 本节试题精选











浙公网安备 33010602011771号