数据结构与算法笔记--堆栈和队列的使用
目录
1--堆栈
1-1--基本概念
1-2--栈的顺序存储
1-2-1--空栈的初始化
1-2-2--入栈操作
1-2-3--出栈操作
1-2-4--测试代码
1-2-5--单个数组实现共享栈
1-3--堆栈的链式存储
1-3-1--定义及创建空栈
1-3-2--判断空栈
1-3-3--入栈操作
1-3-4--出栈操作
1-3-5--测试代码
2--队列
2-1--基本概念
2-2--队列的顺序存储
2-2-1--队列的初始化和销毁
2-2-2--判断空队列
2-2-3--入队操作
2-2-4--出队操作
2-2-5--测试代码
2-3--环形队列
2-3-1--环形队列的初始化和销毁
2-3-2--判断空队列
2-3-3--入队操作
2-3-4--出队操作
2-3-5--测试代码
2-4--队列的链式存储
2-4-1--初始化队列及判断空队列
2-4-2--入队操作
2-4-3--出队操作
2-4-4--销毁队列
2-4-5--测试代码
1--堆栈
1-1--基本概念
堆栈(Stack):具有一定操作约束的线性表,只在一端(栈顶、Top)做插入和删除的操作;
插入数据:入栈(Push);
删除数据:出栈(Pop);
进出顺序:后入先出(Last In First Out, LIFO);
1-2--栈的顺序存储
栈的顺序存储结构通常由一个一维数组和一个记录栈顶元素位置的变量组成,其定义方式如下:
#define MAXSIZE 10
#define ElementType int
typedef struct SNode *Stack;
struct SNode{
ElementType Data[MAXSIZE];
int Top;
};
顺序栈规定:
栈空的条件:S->Top = -1;
栈满的条件:S->Top == MaxSize - 1;
入栈操作:栈顶指针 +1,入栈元素放在栈顶指针处;
出栈操作:取出栈顶指针元素,栈底指针 -1;
1-2-1--空栈的初始化
// 初始化空栈
Stack CreateStack(){
Stack S = (Stack)malloc(sizeof(struct SNode));
S->Top = -1;
return S;
}
1-2-2--入栈操作
// 入栈
bool Push(Stack S, ElementType item){
if(S->Top == MAXSIZE - 1){
std::cout << "The Stack is Full!" << std::endl;
return false;
}
else{
S->Data[++(S->Top)] = item; // 先自增,再赋值
return true;
}
}
1-2-3--出栈操作
// 出栈
ElementType Pop(Stack S){
if(S->Top == -1){
std::cout << "The Stack is Empty!" << std::endl;
return ERROR; //错误值
}
else{
return(S->Data[(S->Top)--]); // 先返回,再自减
}
}
1-2-4--测试代码
#include "iostream"
#define ERROR -9999
#define MAXSIZE 10
#define ElementType int
typedef struct SNode *Stack;
struct SNode{
ElementType Data[MAXSIZE];
int Top;
};
// 初始化空栈
Stack CreateStack(){
Stack S = (Stack)malloc(sizeof(struct SNode));
S->Top = -1;
return S;
}
// 入栈
bool Push(Stack S, ElementType item){
if(S->Top == MAXSIZE - 1){
std::cout << "The Stack is Full!" << std::endl;
return false;
}
else{
S->Data[++(S->Top)] = item; // 先自增,再赋值
return true;
}
}
// 出栈
ElementType Pop(Stack S){
if(S->Top == -1){
std::cout << "The Stack is Empty!" << std::endl;
return ERROR; //错误值
}
else{
return(S->Data[(S->Top)--]); // 先返回,再自减
}
}
int main(int argc, char* argv[]){
Stack S = CreateStack();
std::cout << S->Top << std::endl;
Push(S, 10);
Push(S, 20);
Push(S, 30);
int item1 = Pop(S);
int item2 = Pop(S);
int item3 = Pop(S);
std::cout << "item1: " << item1 << " item2: "
<< item2 << " item3: " << item3 << std::endl;
return 0;
}
1-2-5--单个数组实现共享栈
共享栈:
利用一个数组实现两个栈,两个栈共享数组空间,可以有效避免存储空间的浪费;
共享栈规定:
栈空的条件:栈1空为S->Top1 == -1;栈2空为S->Top2 == MaxSize;
栈满的条件:S->Top1 == S->Top2 - 1;
入栈操作:若入栈1,则S->Top1++,元素放在Top1栈顶指针处;
若入栈2,则S->Top2--,元素放在Top2栈顶指针处;
出栈操作:
若出栈1,则取栈顶Top1指针的元素,同时S->Top1--;
若出栈2,则取栈顶Top2指针的元素,同时S->Top2++;
完整代码:
#include "iostream"
#define ERROR -9999
#define MAXSIZE 10
#define ElementType int
typedef struct SNode *DStack;
struct SNode{
ElementType Data[MAXSIZE];
int Top1;
int Top2;
};
// 创建空堆栈
DStack CreateStack(int MaxSize){
DStack DS = (DStack)malloc(sizeof(struct SNode));
DS->Top1 = -1;
DS->Top2 = MaxSize;
return DS;
}
// 入栈
bool Push(DStack DS, ElementType item, int Tag){
if(DS->Top2 == DS->Top2 + 1){
std::cout << "The Stack is empty!";
return false;
}
if(Tag == 1){
DS->Data[++(DS->Top1)] = item; // 先自增,再赋值
}
else{
DS->Data[--(DS->Top2)] = item; // 先自减,再赋值
}
return true;
}
// 出栈
ElementType Pop(DStack DS, int Tag){
if(Tag == 1){ // 第一个堆栈
if(DS->Top1 == -1){
std::cout << "The First Stack is Empty!" << std::endl;
return ERROR;
}
else{
return DS->Data[(DS->Top1)--]; // 先返回,再自减
}
}
else{ // 第二个堆栈
if(DS->Top2 == MAXSIZE){
std::cout << "The Second Stack is Empty!" << std::endl;
return ERROR;
}
else{
return DS->Data[(DS->Top2)++]; // 先返回,再自增
}
}
}
int main(int argc, char* argv[]){
DStack DS = CreateStack(MAXSIZE);
Push(DS, 10, 1);
Push(DS, 20, 1);
Push(DS, 30, 2);
ElementType elem1 = Pop(DS, 1);
ElementType elem2 = Pop(DS, 1);
ElementType elem3 = Pop(DS, 2);
std::cout << "elem1: " << elem1 << " elem2: " << elem2
<< " elem3: " << elem3 << std::endl;
return 0;
}
1-3--堆栈的链式存储
链栈规定:
栈空的条件是:S->next ==NULL;
栈满的条件是:内存溢出才出现栈满,一般不考虑栈满的情况;
入栈操作:申请新结点存放入栈元素,并将头结点指向新结点;
出栈操作:取首结点元素,并释放首结点;
1-3-1--定义及创建空栈
#define ElementType int
typedef struct SNode* Stack;
struct SNode{
ElementType Data;
struct SNode* Next;
};
// 初始化空栈
Stack CreateStack(){
Stack S;
S = (Stack)malloc(sizeof(struct SNode));
S->Next = NULL;
return S;
}
1-3-2--判断空栈
// 判断栈是否为空
int IsEmpty(Stack S){
return(S->Next == NULL);
}
1-3-3--入栈操作
// 入栈
bool Push(ElementType item, Stack S){
struct SNode *Tem;
Tem = (struct SNode*)malloc(sizeof(struct SNode));
Tem->Data = item;
Tem->Next = S->Next;
S->Next = Tem;
return true;
}
1-3-4--出栈操作
// 出栈
ElementType Pop(Stack S){
struct SNode *Tem;
ElementType TopElem;
if(IsEmpty(S)){
std::cout << "The Stack is empty!" << std::endl;
return ERROR;
}
else{
Tem = S->Next;
S->Next = Tem->Next;
TopElem = Tem->Data;
free(Tem);
return TopElem;
}
}
1-3-5--测试代码
#include "iostream"
#define ERROR -9999
#define ElementType int
typedef struct SNode* Stack;
struct SNode{
ElementType Data;
struct SNode* Next;
};
// 初始化空栈
Stack CreateStack(){
Stack S;
S = (Stack)malloc(sizeof(struct SNode));
S->Next = NULL;
return S;
}
// 判断栈是否为空
int IsEmpty(Stack S){
return(S->Next == NULL);
}
// 入栈
bool Push(ElementType item, Stack S){
struct SNode *Tem;
Tem = (struct SNode*)malloc(sizeof(struct SNode));
Tem->Data = item;
Tem->Next = S->Next;
S->Next = Tem;
return true;
}
// 出栈
ElementType Pop(Stack S){
struct SNode *Tem;
ElementType TopElem;
if(IsEmpty(S)){
std::cout << "The Stack is empty!" << std::endl;
return ERROR;
}
else{
Tem = S->Next;
S->Next = Tem->Next;
TopElem = Tem->Data;
free(Tem);
return TopElem;
}
}
// 销毁栈
void DestroyStack(Stack S){
Stack cur = S, nex = S->Next;
while(nex != NULL){
free(cur);
cur = nex;
nex = nex->Next;
};
free(cur);
}
int main(int argc, char *argv[]){
Stack S = CreateStack();
Push(10, S);
Push(20, S);
Push(30, S);
ElementType elem1 = Pop(S);
ElementType elem2 = Pop(S);
ElementType elem3 = Pop(S);
std::cout << "elem1: " << elem1 << " elem2: " << elem2
<< " elem3: " << elem3 << std::endl;
DestroyStack(S);
return 0;
}
2--队列
2-1--基本概念
队列:表示具有一定操作约束的线性表,其只能在一端插入,而在另一端删除;
数据插入:入队列(AddQ)
删除删除:出队列(DeleteQ)
进出顺序:先进先出(FIFO)
2-2--队列的顺序存储
顺序队规定:
① 队头指针 front 指向队列中第一个元素的前一个位置;
② 队尾指针 rear 指向队列中最后一个元素的位置;
③ 队空的条件:q->front == q->rear;
④ 队满的条件:q->rear == MaxSize - 1;
⑤ 入队操作:rear +1,将入队元素放在 rear 位置;
⑥ 出队操作:front +1,取出 front 位置的元素;
// 队列的声明
#define ElemType int
#define MaxSize 10
struct Queue{
ElemType data[MaxSize];
int front, rear;
};
using SQueue = Queue*;
2-2-1--队列的初始化和销毁
// 初始化队列
void InitQueue(SQueue &q){
q = (SQueue)malloc(sizeof(Queue));
q->front = q->rear = -1;
}
// 销毁队列
void DestroyQueue(SQueue &q){
free(q);
}
2-2-2--判断空队列
// 判断队列是否为空
bool QueueEmpty(SQueue &q){
return (q->front == q->rear);
}
2-2-3--入队操作
// 入队
bool enQueue(SQueue &q, ElemType e){
if(q->rear == MaxSize - 1){ // 队满
return false;
}
else{
q->rear++;
q->data[q->rear] = e;
return true;
}
}
2-2-4--出队操作
// 出队
bool deQueue(SQueue &q, ElemType &e){
if(q->front==q->rear){
return false;
}
else{
q->front++;
e = q->data[q->front];
return true;
}
}
2-2-5--测试代码
#include "iostream"
#define ElemType int
#define MaxSize 10
struct Queue{
ElemType data[MaxSize];
int front, rear;
};
using SQueue = Queue*;
// 初始化队列
void InitQueue(SQueue &q){
q = (SQueue)malloc(sizeof(Queue));
q->front = q->rear = -1;
}
// 入队
bool enQueue(SQueue &q, ElemType e){
if(q->rear == MaxSize - 1){ // 队满
return false;
}
else{
q->rear++;
q->data[q->rear] = e;
return true;
}
}
// 出队
bool deQueue(SQueue &q, ElemType &e){
if(q->front==q->rear){
return false;
}
else{
q->front++;
e = q->data[q->front];
return true;
}
}
// 判断队列是否为空
bool QueueEmpty(SQueue &q){
return (q->front == q->rear);
}
// 销毁队列
void DestroyQueue(SQueue &q){
free(q);
}
int main(int argc, char* argv[]){
SQueue q;
InitQueue(q); // 初始化
enQueue(q, 10); // 入队
enQueue(q, 20);
enQueue(q, 30);
ElemType item1, item2, item3;
deQueue(q, item1); // 出队
deQueue(q, item2);
deQueue(q, item3);
std::cout << "item1: " << item1 << " item2: " << item2
<< " item3: " << item3 << std::endl;
bool ret = QueueEmpty(q); // 判断是否为空
if(ret){
std::cout << "The Queue is empty!" << std::endl;
}
DestroyQueue(q); // 销毁队列
return 0;
}
2-3--环形队列
环形队列规定:
① 队空条件:q->front == q->rear;
② 堆满条件:(q->rear +1) % MaxSize == q->front;
2-3-1--环形队列的初始化和销毁
// 初始化队列
void InitQueue(SQueue &q){
q = (SQueue)malloc(sizeof(Queue));
q->front = q->rear = 0;
}
// 销毁队列
void DestroyQueue(SQueue &q){
free(q);
}
2-3-2--判断空队列
// 判断队列是否为空
bool QueueEmpty(SQueue &q){
return (q->front == q->rear);
}
2-3-3--入队操作
// 入队
bool enQueue(SQueue &q, ElemType e){
if((q->rear +1) % MaxSize == q->front){ // 队满
return false;
}
else{
q->rear = (q->rear+1) % MaxSize;
q->data[q->rear] = e;
return true;
}
}
2-3-4--出队操作
// 出队
bool deQueue(SQueue &q, ElemType &e){
if(q->front==q->rear){
return false;
}
else{
q->front = (q->front +1) % MaxSize;
e = q->data[q->front];
return true;
}
}
2-3-5--测试代码
#include "iostream"
#define ElemType int
#define MaxSize 10
struct Queue{
ElemType data[MaxSize];
int front, rear;
};
using SQueue = Queue*;
// 初始化队列
void InitQueue(SQueue &q){
q = (SQueue)malloc(sizeof(Queue));
q->front = q->rear = 0;
}
// 入队
bool enQueue(SQueue &q, ElemType e){
if((q->rear +1) % MaxSize == q->front){ // 队满
return false;
}
else{
q->rear = (q->rear+1) % MaxSize;
q->data[q->rear] = e;
return true;
}
}
// 出队
bool deQueue(SQueue &q, ElemType &e){
if(q->front==q->rear){
return false;
}
else{
q->front = (q->front +1) % MaxSize;
e = q->data[q->front];
return true;
}
}
// 判断队列是否为空
bool QueueEmpty(SQueue &q){
return (q->front == q->rear);
}
// 销毁队列
void DestroyQueue(SQueue &q){
free(q);
}
int main(int argc, char* argv[]){
SQueue q;
InitQueue(q); // 初始化
enQueue(q, 10); // 入队
enQueue(q, 20);
enQueue(q, 30);
ElemType item1, item2, item3;
deQueue(q, item1); // 出队
deQueue(q, item2);
deQueue(q, item3);
std::cout << "item1: " << item1 << " item2: " << item2
<< " item3: " << item3 << std::endl;
bool ret = QueueEmpty(q); // 判断是否为空
if(ret){
std::cout << "The Queue is empty!" << std::endl;
}
DestroyQueue(q); // 销毁队列
return 0;
}
2-4--队列的链式存储
采用链式存储结构的队列称为链队,其定义方式如下:
#define ElementType int
struct QueueNode{ // 结点
ElementType Data;
QueueNode* Next;
};
using LQNode = QueueNode*;
struct LinkQueue{ // 链队
LQNode front, rear;
};
using LQueue = LinkQueue*;
链队规定:
① 队空的条件:q->rear == NULL; 或 q->front == NULL;
② 堆满的条件:一般不考虑;
③ 入队操作:申请新结点存放入队元素,将新结点作为新的尾结点;
④ 出队操作:取出队首结点的数据,并将其释放;
2-4-1--初始化队列及判断空队列
// 初始化空链队列
LQueue InitLQueue(){
LQueue q = (LQueue)malloc(sizeof(struct LinkQueue));
q->front = q->rear = NULL;
return q;
}
// 判断队列是否为空
bool QueueEmpty(LQueue q){
return (q->front == NULL);
}
2-4-2--入队操作
// 入队列
void enQueue(LQueue q, ElementType e){
LQNode n = (LQNode)malloc(sizeof(struct QueueNode)); //申请新结点
n->Data = e;
n->Next = NULL;
if(q->rear == NULL){ // 队列为空
q->front = q->rear = n;
}
else{
q->rear->Next = n; // 原尾结点指向新结点
q->rear = n; // 新结点作为新尾结点
}
}
2-4-3--出队操作
// 出队列
bool deQueue(LQueue q, ElementType &e){
if(q->rear == NULL){ // 队列为空
return false;
}
else{
LQNode tmp = q -> front;
if(q->front == q->rear){ // 只有一个元素
q->front = q->rear = NULL;
}
else{
q->front = q->front->Next;
}
e = tmp->Data;
free(tmp);
return true;
}
}
2-4-4--销毁队列
// 销毁队列
void DestroyQueue(LQueue q){
LQNode cur = q->front, nex;
if(cur != NULL){
nex = cur->Next;
while(nex != NULL){
free(cur);
cur = nex;
nex = nex->Next;
}
free(cur);
}
free(q);
}
2-4-5--测试代码
#include "iostream"
#define ElementType int
struct QueueNode{
ElementType Data;
QueueNode* Next;
};
using LQNode = QueueNode*;
struct LinkQueue{
LQNode front, rear;
};
using LQueue = LinkQueue*;
// 初始化空链队列
LQueue InitLQueue(){
LQueue q = (LQueue)malloc(sizeof(struct LinkQueue));
q->front = q->rear = NULL;
return q;
}
// 判断队列是否为空
bool QueueEmpty(LQueue q){
return (q->front == NULL);
}
// 入队列
void enQueue(LQueue q, ElementType e){
LQNode n = (LQNode)malloc(sizeof(struct QueueNode)); //申请新结点
n->Data = e;
n->Next = NULL;
if(q->rear == NULL){ // 队列为空
q->front = q->rear = n;
}
else{
q->rear->Next = n; // 原尾结点指向新结点
q->rear = n; // 新结点作为新尾结点
}
}
// 出队列
bool deQueue(LQueue q, ElementType &e){
if(q->rear == NULL){ // 队列为空
return false;
}
else{
LQNode tmp = q -> front;
if(q->front == q->rear){ // 只有一个元素
q->front = q->rear = NULL;
}
else{
q->front = q->front->Next;
}
e = tmp->Data;
free(tmp);
return true;
}
}
// 销毁队列
void DestroyQueue(LQueue q){
LQNode cur = q->front, nex;
if(cur != NULL){
nex = cur->Next;
while(nex != NULL){
free(cur);
cur = nex;
nex = nex->Next;
}
free(cur);
}
free(q);
}
int main(int argc, char *argv[]){
LQueue q = InitLQueue();
// 入队列
enQueue(q, 10);
enQueue(q, 20);
enQueue(q, 30);
// 出队列
ElementType item1, item2, item3;
deQueue(q, item1);
deQueue(q, item2);
deQueue(q, item3);
std::cout << "item1: " << item1 << " item2: " << item2
<< " item3: " << item3 << std::endl;
if(QueueEmpty(q)){
std::cout << "The Queue is empty!" << std::endl;
}
DestroyQueue(q);
return 0;
}