栈的链式存储结构
栈的链式存储结构通常使用单链表来实现,其中链表的头部作为栈顶,尾部作为栈底(尽管在栈的实际操作中我们并不关心栈底)。栈的链式存储结构通常不需要存储栈的最大容量,因为链表可以动态地增长和收缩。
栈的链式存储结构定义(使用C语言):
typedef struct Node {
int data;
struct Node *next;
} Node, *Stack;
基本操作:
1、初始化栈:创建一个空节点,并将其地址赋给栈顶指针。
Stack InitStack() {
Stack S = (Stack)malloc(sizeof(Node));
if (!S) {
exit(EXIT_FAILURE);
}
S->next = NULL; // 栈顶指向空
return S;
}
2、判断栈是否为空:如果栈顶指针的下一个节点为空,则栈为空。
int StackEmpty(Stack S) {
return S->next == NULL;
}
3、入栈:创建一个新节点,将数据放入该节点,然后将新节点插入到栈顶。
void Push(Stack S, int e) {
Node *newNode = (Node*)malloc(sizeof(Node));
if (!newNode) {
exit(EXIT_FAILURE);
}
newNode->data = e;
newNode->next = S->next; // 新节点指向原栈顶节点
S->next = newNode; // 更新栈顶指针
}
4、出栈:移除栈顶节点,并释放其内存。
int Pop(Stack S, int *e) {
if (StackEmpty(S)) {
return 0; // 出栈失败
}
Node *temp = S->next; // 临时保存栈顶节点
*e = temp->data; // 保存数据
S->next = temp->next; // 更新栈顶指针
free(temp); // 释放原栈顶节点内存
return 1; // 出栈成功
}
5、取栈顶元素:返回栈顶节点的数据,但不移除该节点。
int GetTop(Stack S, int *e) {
if (StackEmpty(S)) {
return 0; // 获取失败
}
*e = S->next->data;
return 1; // 获取成功
}
队列的链式存储结构
队列的链式存储结构也使用单链表来实现,但队列需要维护两个指针:一个指向队头(front),另一个指向队尾(rear)。队列的链式存储结构允许队列在两端进行插入和删除操作。
队列的链式存储结构定义(使用C语言):
typedef struct Node {
int data;
struct Node *next;
} Node;
typedef struct {
Node *front; // 队头指针
Node *rear; // 队尾指针
} Queue;
基本操作(与栈类似,但队列在队尾插入元素,在队头删除元素):
1、初始化队列:创建两个空指针,分别作为队头和队尾。
Queue InitQueue() {
Queue Q;
Q.front = Q.rear = NULL;
return Q;
}
2、判断队列是否为空:如果队头指针为空,则队列为空。
int QueueEmpty(Queue Q) {
return Q.front == NULL;
}
3、入队:在队尾插入一个新节点。
void EnQueue(Queue *Q, int e) {
Node *newNode = (Node*)malloc(sizeof(Node));
if (!newNode) {
exit(EXIT_FAILURE);
}
newNode->data = e;
newNode->next = NULL; // 新节点为最后一个节点
if (QueueEmpty(*Q)) { // 如果队列为空,则新节点同时是队头和队尾
Q->front = Q->rear = newNode;
} else { // 否则,新节点成为队尾节点,原队尾节点的next指向新节点
Q->rear->next = newNode;
Q->rear = newNode;
}
}
4、出队:移除队头节点,并释放其内存。
int DeQueue(Queue *Q, int *e) {
if (QueueEmpty(*Q)) {
return 0; // 出队失败
}
Node *temp = Q->front; // 临时保存队头节点
*e = temp->data; // 保存数据
Q->front = temp->next; // 更新队头指针
if (Q->front == NULL) { // 如果队列为空,队尾指针也为空
Q->rear = NULL;
}
free(temp); // 释放原队头节点内存
return 1; // 出队成功
}
5、取队头元素:返回队头节点的数据,但不移除该节点。
int GetFront(Queue Q, int *e) {
if (QueueEmpty(Q)) {
return 0; // 获取失败
}
*e = Q.front->data;
return 1; // 获取成功
}