第三章_栈和队列
主要参考了王道的书,主要针对考研
3.1栈
3.1.1 栈的概述
-
栈的定义
只允许一端(栈顶top)操作,先进后出
n个不同元素出栈的不同排列组合个数为(1/(n+1))C(n,2n)
-
栈的基本操作
//初始化栈 void StackInit(stack& s); //判断栈空 bool isEmpty(stack s); //判断栈满 bool isFull(stack s); //入栈,把x元素放入栈中 bool Push(stack& s, ElementType x); //出栈,把出栈的元素赋值给x bool Pop(stack& s, ElementType& x); //判断栈满 bool isFull(stack s); //读取栈顶元素 int getTop(stack& s);
3.1.2 顺序栈
- 存储类型
#define MAXSIZE 6
typedef int ElementType;//定义数据类型
//定义栈的存储结构
typedef struct stack {
ElementType data[MAXSIZE];//存放栈中的数据
int top;//记录栈顶的下标
}stack;
-
初始化
//初始化栈 void StackInit(stack &s) { s.top = -1; }
-
判断空
//判断栈空
bool isEmpty(stack s)
{
if (s.top == -1)
return true;
return false;
}
- 判断满
//判断栈满
bool isFull(stack s)
{
if (s.top == MAXSIZE-1)
return true;
return false;
}
- 入栈
//入栈,把x元素放入栈中
bool Push(stack& s,ElementType x)
{
//判断栈是否满了,如果是空的就不能入栈
if (isFull(s))
{
printf("栈满不能入栈\n");
return false;
}
s.top++;
s.data[s.top] = x;
return true;
}
-
出栈
//出栈,把出栈的元素赋值给x bool Pop(stack& s, ElementType& x) { //判断栈是否为空,如果是空的就不能再出栈了 if (isEmpty(s)) { printf("栈空了不能出栈"); return false; } x = s.data[s.top]; s.top--; return true; }
-
读取栈顶元素
//读取栈顶元素 int getTop(stack& s) { if (isEmpty(s)) { printf("栈为空,不能读取栈顶元素"); return -1; } return s.data[s.top]; }
顺序栈的实现
//顺序栈的实现
#define MAXSIZE 6
#include <stdio.h>
#include <stdlib.h>
typedef int ElementType;//定义数据类型
//定义栈的存储结构
typedef struct stack {
ElementType data[MAXSIZE];//存放栈中的数据
int top;//记录栈顶的下标
}stack;
//1.初始化栈
void StackInit(stack& s);
//2.判断栈空
bool isEmpty(stack s);
//3.判断栈满
bool isFull(stack s);
//4.入栈,把x元素放入栈中
bool Push(stack& s, ElementType x);
//5.出栈,把出栈的元素赋值给x
bool Pop(stack& s, ElementType& x);
//6.读取栈顶元素
int getTop(stack& s);
int main()
{
stack s;
StackInit(s);
//判断栈是否为空
printf("栈是否为空:%d\n", isEmpty(s));
//入栈
for (int i = 0; i < 6; i++)
{
Push(s, i+1);
}
//判断栈是否为满
printf("栈是否为满:%d\n", isFull(s));
//读取栈顶元素
ElementType e = 0;
e=getTop(s);
printf("目前栈顶元素是%d\n\n", e);
//出栈
for (int i = 0; i < 6; i++)
{
Pop(s, e);
printf("目前出栈的元素是%d\n", e);
e = getTop(s);
if (e != -1)
printf("目前栈顶元素是%d\n\n", e);
}
}
//1.初始化栈
void StackInit(stack &s)
{
s.top = -1;
}
//2.判断栈空
bool isEmpty(stack s)
{
if (s.top == -1)
return true;
return false;
}
//3.判断栈满
bool isFull(stack s)
{
if (s.top == MAXSIZE-1)
return true;
return false;
}
//4.入栈,把x元素放入栈中
bool Push(stack& s,ElementType x)
{
//判断栈是否满了,如果是空的就不能入栈
if (isFull(s))
{
printf("栈满不能入栈\n");
return false;
}
s.top++;
s.data[s.top] = x;
return true;
}
//5.出栈,把出栈的元素赋值给x
bool Pop(stack& s, ElementType& x)
{
//判断栈是否为空,如果是空的就不能再出栈了
if (isEmpty(s))
{
printf("栈空了不能出栈");
return false;
}
x = s.data[s.top];
s.top--;
return true;
}
//6.读取栈顶元素
int getTop(stack& s)
{
if (isEmpty(s))
{
printf("栈为空,不能读取栈顶元素");
return -1;
}
return s.data[s.top];
}
3.1.3 链栈
链栈的优点在于便于多个栈共享存储空间和提高效率,其实就是带头节点的链表进行头插法和头部删去法
3.2队列
3.2.1 队列的基本概念
-
定义
一端插入,一端删除,先进先出
插入称入队(从队尾插入),删除称出队(从队头删除)
-
基本操作
3.2.2 顺序队列
- 队列的顺序存储
分配一块连续的存储空间存放队列中的元素,头指针front和尾指针rear分别指向队头元素和队尾元素的下一个位置。
初始状态:front==rear==0
进队:队不满,rear+1
出队:队不空,front+1
这种队列判断满比较复杂,于是有了循环队列
比如增加一个size来看是否和MAXSIZE相等,或者用一个flag来标志,插入导致rearfront则为满,删除导致rearfront则为空
-
循环队列
用一个额外的空间判断满:(rear+1)%MAXSIZE==front
循环队列的实现
/*循环顺序队列的实现*/
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 6
typedef int ElementType ;
//定义队列的数据类型
typedef struct queue
{
ElementType* data;
int rear;//尾指针,记录队尾后一个元素的下标
int front;//头指针,记录队头的下标
}queue;
//1.队列的初始化
void QueueInit(queue& q);
//2.判断队列是否为空
bool isEmpty(queue q);
//3.判断队列是否已满
bool isFull(queue q);
//4.出队
bool DeQueue(queue& q, ElementType& x);
//5.入队
bool EnQueue(queue& q, ElementType e);
//6.统计队列中有多少个元素
int QueueLen(queue q);
int main()
{
queue q;
QueueInit(q);//初始化队列
printf("队列是否为空:%d\n", isEmpty(q));//判空
for(int i=0;i<MAXSIZE;i++)
EnQueue(q,i+1);//入队
printf("队列中有%d个元素\n", QueueLen(q));
printf("队列是否为满:%d\n", isFull(q));//判满
ElementType e;
printf("sss:%d\n", q.data[4]);
if(DeQueue(q, e))
printf("当前出队的元素是:%d\n", e);
printf("队列中有%d个元素\n", QueueLen(q));
}
//1.队列的初始化
void QueueInit(queue& q)
{
q.data = (ElementType*)malloc(sizeof(ElementType) * MAXSIZE);
q.rear = 0;
q.front = 0;
}
//2.判断队列是否为空
bool isEmpty(queue q)
{
return q.rear == q.front;
}
//3判断队列是否已满
bool isFull(queue q)
{
return (q.rear + 1) % MAXSIZE == q.front;
}
//4出队,x用来存出队的元素
bool DeQueue(queue &q,ElementType& x)
{
//队列为空不能出队
if (isEmpty(q))
return false;
x = q.data[q.front];
q.front = (q.front + 1) % MAXSIZE;
return true;
}
//5入队
bool EnQueue(queue &q,ElementType e)
{
if (isFull(q))//队列满了不能入队
return false;
q.data[q.rear] = e;
q.rear = (q.rear + 1) % MAXSIZE;
return true;
}
//6.统计队列中有多少个元素
int QueueLen(queue q)
{
return (q.rear - q.front + MAXSIZE) % MAXSIZE;
}