栈的定义
栈(stack)是限定仅在表尾进行插入和删除操作的线性表。 用白话说:先进后出,后进先出,谁进的晚,谁出的早。
抽象数据类型
ADT 栈(Stack)
Data
Operation:
InitStack(*S);
StackEmpty(S);
ClearStack(*S);
GetTop(S,*e);
Push(*S,e)
Pop(*S,*e);
Length(L);
end ADT
栈的顺序存储结构
typedef struct
{
SElemType data[MAXSIZE];
int top;
}SqStack;
可以看到,用top指针来指向栈顶元素,实现进栈,出栈等操作。
栈的顺序存储的主要缺陷就是必须事先申请所需存储空间的大小,万一不够用,就必须使用编程手段来扩展数组的容量。
栈的链式存储结构
栈顶就放在单链表的头部,结构代码:
typedef struct StackNode
{
SElemType data;
struct StackNode *next;
}StackNode, *LinkStackPtr;
typedef struct LinkStack
{
LinkStackPtr top;
int count;
}LinkStack;
多说一句,如果是两个相同数据类型的栈,可以用数组的两端做栈底的方法来让两个栈共享数据,最大化地利用数组的空间。
队列的定义
队列(Queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表 用白话说:先进先出,后进后出。
抽象数据类型
ADT 队列(Queue)
Data
Operation:
InitQueue(*Q);
QueueEmpty(Q);
ClearQueue(*Q);
GetHead(Q,*e);
DeQueue(*Q,e)
EnQueue(*Q,*e);
Length(Q);
end ADT
队列的顺序存储结构
队列的顺序存储结构可不像栈那么简单。出栈操作是在数组尾,而出队列操作是在队列头,这就意味着在出队和入队的过程中,队列中的元素都得向前移动,以保证队头元素下标为0,这样出队列的时间复杂度变为了O(n),这显然不是我们想要的,所以我们在队列中定义队头不一定要下标为0,我们引入两个指针:
- front:指向队头元素
- rear:指向队尾元素
同时,要注意,队列的定义是循环的,即队列的数组首尾相接,rear到数组尾后直接回到数组头,可以继续使用之前出队列所空出来的空间。
Plus-通用的计算队列长度公式:
(
r
e
a
r
−
f
r
o
n
t
+
Q
u
e
u
e
S
i
z
e
)
%
Q
u
e
u
e
S
i
z
e
(rear - front + QueueSize) \% QueueSize
(rear−front+QueueSize)%QueueSize
其中QueueSize为队列的最大尺寸。
结构代码:
typedef struct
{
QElemType data[MAXSIZE];
int front;
int rear;
}SqQueue;
队列的链式存储结构
typedef struct QNode
{
QElemType data;
struct QNode *next;
}QNode, *QueuePtr;
typedef struct
{
QueuePtr front, rear;
}LinkQueue;