标签:顺序存储结构 求值 void 压缩 its max 循环 lse 这一
目录
? 该系列博客的目的是为了学习一遍数据结构中常用的概念以及常用的算法,为笔试准备;主要学习过程参考王道的《2018年-数据结构-考研复习指导》;
已总结章节:
? 上篇博客《数据结构与算法》-2-线性表中介绍了线性结构中的线性表的定义、基本操作以及线性表的两种存储方式:顺序存储与链式存储;这一篇博客将主要介绍线性结构中的受限线性表:栈、队列。
? 主要包含的内容有:
? 其知识框架如下图所示:
栈(Stack):
? 只能在一端插入或删除操作的线性表;
栈顶(Top):
? 线性表允许执行插入或删除操作的一端;
栈底(Botton):
? 线性表不允许执行插入或删除操作的一端;
注意:根据栈的定义可以得到,栈是先进后出的线性表;
InitStack(&S)
:初始化一个空栈S;
StackEmpty(S)
:判断S是否为空栈;
Push(&S, x)
:进栈操作;若未满,则将x进栈,作为栈顶;
Pop(&S, &x)
:出栈操作;若非空,则将栈S的栈顶元素弹出,并用x返回;
GetTop(S, &x)
:读取栈顶元素;若非空,用x返回栈顶元素;
ClearStack(&S)
:销毁栈,并释放其存储空间;
? 栈的顺序存储称为顺序栈,它是利用一组地址连续的存储单元存放从栈底到栈顶的所有数据元素,同时附设一个指针top,指向当前栈顶位置。
? 栈的顺序存储类型描述:
# define MaxSize 50
typedef struct{
ElemType data[MaxSize];
int top;
}SqStack;
S.top
,初始时S.top=-1
;S.data[S.top]
;S.top==-1
;S.top == MaxSize -1
;初始化:
void InitStack(&S){
S.top = -1;
}
判栈空:
bool StackEmpty(S){
if(S.top == -1)
return true;
else
return false;
}
进栈:
bool Push(&S, x){
if(S.top == MaxSize-1)
return false;
else
s.top++;
S.data[S.top] = x; // 或 S.data[++S.top] = x;
return true;
}
出栈:
bool Pop(&S, &x){
if(S.top == -1)
return false;
x = S.data[S.top];
S.top--; // 或 x = S.data[S.top--]
return true;
}
读栈顶元素:
bool GetTop(S, &x){
if(S.top == -1)
return false;
x = S.data[S.top];
return true;
}
? 利用栈底位置不变的特性,可以让两个顺序栈共享一个一维数组,如下图所示:
s0.top = -1
表示0号栈栈空;s1.top = MaxSize -1
表示1号栈栈空;s1.top - s0.top = 1
表示栈满;1号栈,进栈时,指针先减1,再赋值;出栈时,先赋值,再加1;
共享栈的目的是为了更有效地利用存储空间;
? 栈的顺序存储称为顺序栈,那么采用链式存储的栈则称为链栈;
? 优点:便于多个栈共享存储空间和提高效率,不存在栈满溢出的情况;
? 采用单链表来实现,并规定所有操作再单链表表头进行,没有头结点;Lhead指向栈顶元素;如图所示:
? 栈的链式存储的类型描述:
typedef struct Linknode{
ElemType data;
struct Linknode *next;
}*LiStack;
队列(Queue):
? 只允许在表的一端插入,另一端删除;
队头(Front):
? 允许删除的一端;
对尾(Rear):
? 允许插入的一端;
空队列:
? 不含任何元素的空表;
注意:根据队列的定义可以得到,队列是先进先出的线性表;
InitQueue(&Q)
:初始化队列,构造一个空队列Q;
QueueEmpty(Q)
:判空;
EnQueue(&Q, x)
:入队操作;先判满,再入队;
DeQueue(&Q, &x)
:出队操作;先判空,再出队,并用x返回;
GetHead(Q, &x)
:读队头元素,并用x返回;
? 队列的顺序实现是指:分配一块连续的存储单元存放队列中的元素;
? 队列的顺序存储类型描述:
#define MaxSize 50
typedef struct{
ElemType data[MaxSize];
int front, rear;
}SqQueue;
Q.front == Q.rear == 0
;? 上面讲述了队列顺序存储时的判空条件,即Q.front == Q.rear == 0
;那么判满条件呢?是Q.rear == MaxSize -1
吗?显然不是,假如队头已经有出队的元素,这时候是一种“假溢出”;
? 为解决上述队列顺序存储的缺点,这里有了一种循环队列,即当队头指针Q.front == MaxSize -1
,或队尾指针Q.rear == MaxSize -1
时,再前进一个位置时,会自动到0;
Q.front = Q.rear = 0
;Q.front = (Q.front + 1) % MaxSize
;Q.rear = (Q.rear + 1) % MaxSize
;Q.rear + MaxSize - Q.front) % MaxSize
;? 从上图可以看出,初始化时Q.front = Q.rear
;当入队操作多于出队操作时,队尾指针很快就能赶上队头指针,当Q.front = Q.rear
时(图d1),也代表队满;
? 那么Q.front = Q.rear
即可以表示队空,也可以表示队满?那怎么来区分呢?这里有三种处理方式:
(Q.rear + 1) % MaxSize = Q.front
;Q.front == Q.rear
;Q.rear + MaxSize - Q.front) % MaxSize
;Q.size
;
Q.size = MaxSize -1
;Q.size = 0
;tag=0
,因删除导致Q.front = Q.rear
,则表示队空;tag=1
,因插入导致Q.front = Q.rear
,则表示队满;初始化:
void InitQueue(&Q){
Q.rear = Q.front = 0;
}
判队空:
bool IsEmpty(Q){
if(Q.rear == Q.front)
return true;
else
return false;
}
入队:
bool EnQueue(SqQueue &Q, ElemType x){
if((Q.rear + 1) % MaxSize == Q.front) // 判队满
return false;
Q.data[Q.rear] = x; // 队尾元素赋值
Q.rear = (Q.rear + 1) % MaxSize; // 队尾元素加1
return true;
}
出队:
bool DeQueue(SqQueue &Q, ElemType &x){
if (Q.rear == Q.front) // 判队空
return false;
x = Q.data[Q.front]; // 取出队头元素
Q.front = (Q.front + 1) % MaxSize; // 队头指针加1
return true;
}
? 队列的链式存储称为链队列;它实际上是一个同时带有队头指针和队尾指针的单链表;
? 队列的链式存储类型描述:
typedef struct{
ElemType data;
struct LinkNode *next;
}LinkNode;
typedef struct{
LinkNode *front, *rear;
}LinkQueue;
不带头结点的链式队列:
Q.front == NULL, Q.rear == NULL
时,链式队列为空;带头结点的链式队列:
初始化:
void InitQueue(LinkQueue &Q){
Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode)); // 建立头结点
Q.front -> next = NULLL; // 初始为空
}
判队空:
bool isEmpty(LinkQueue Q){
if(Q.front == Q.rear)
return true;
else
return false;
}
入队:
void EnQueue(LinkQueue &Q, ElemType x){
s = (LinkNode *)malloc(sizeof(LinkNode)); // 新建结点
s -> data = x; // 对新结点数据域赋值
s -> next = NULL; // 将新结点指针域设空
Q.rear -> next = s; // 链表尾插入
Q.rear = s; // 对尾指针指向队尾元素
}
出队:
void DeQueue(LinkQueue &Q, ElemType &x){
if(Q.front == Q.rear) // 判空
return false;
p = Q.front -> next; // 需要出队的结点
x = p -> data; // 赋值
Q.front -> next = p -> next; // 断开p结点
if(Q.rear == p) // 判断原队列只有一个元素
Q.rear = Q.front;
free(p);
return true;
}
? 双端队列指的是两端都可以执行入队、出队操作;
入队:
出队:
? 即有一端只允许入队;
? 即有一端只允许出队;
标签:顺序存储结构 求值 void 压缩 its max 循环 lse 这一
原文地址:https://www.cnblogs.com/chenzhen0530/p/10704816.html