链式栈
定义
链式栈(Linked Stack)是一种基于链表实现的栈(Stack)数据结构。栈是一种具有特定限制条件的线性数据结构,其中元素的插入和删除操作只能在一端进行,该端称为栈顶(Top)。链式栈通过使用链表来存储元素,每个节点包含一个数据元素和一个指向下一个节点的指针。
特点
-
动态大小:链式栈的大小可以根据需要进行动态调整,不受固定大小的限制。链表结构充分利用了内存空间,可以灵活地增加或删除节点,从而适应不同的数据规模。
-
堆内存分配:链式栈的节点是通过堆内存动态分配而成的,而不是通过数组进行连续存储。这意味着链式栈可以处理更大的数据量,不会受到栈空间大小的限制。
-
添加和删除操作效率高:由于链式栈采用了链表结构,插入和删除操作只需要调整节点的指针,时间复杂度为O(1)。因此,无论是入栈还是出栈操作,都能够在常数时间内完成。
代码实现
节点描述
typedef struct LNode {
int val;
LNode* next;
}LNode;
栈描述
typedef struct LinkStack {
LNode* head;
int size;
}LinkStack;
初始化
void InitStack(LinkStack* slink) {
assert(slink != NULL);
slink->head = NULL;
slink->size = 0;
}
创建节点
LNode* CreatNode(int val) {
LNode* p = (LNode*)malloc(sizeof(LNode));
assert(p != NULL);
p->val = val;
p->next = NULL;
return p;
}
判空
bool IsEmpty(LinkStack* slink) {
return slink->size == NULL;
}
入栈
bool Push(LinkStack* slink, int val) {
assert(slink != NULL);
LNode* p = CreatNode(val);
p->next = slink->head;
slink->head = p;
slink->size++;
return true;
}
出栈
bool Pop(LinkStack* slink) {
if (IsEmpty(slink)) {
return false;
}
else {
LNode* p = slink->head;
slink->head = p->next;
free(p);
return true;
}
}
获取栈顶元素
bool GetTop(LinkStack* slink,int* pval) {
if (IsEmpty(slink)) {
*pval = 0;
return false;
}
else {
*pval = slink->head->val;
return true;
}
}
获取栈中有效元素个数
int GetSize(LinkStack* slink) {
return slink->size;
}
清空栈
void ClearStack(LinkStack* slink) {
LNode* p = slink->head;
while (p->next != NULL) {
p->val = 0;
p = p->next;
}
}
销毁栈
void DestoryStack(LinkStack* slink) {
while (Pop(slink));
}
完整代码
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
typedef struct LNode {
int val;
LNode* next;
}LNode;
typedef struct LinkStack {
LNode* head;
int size;
}LinkStack;
LNode* CreatNode(int val) {
LNode* p = (LNode*)malloc(sizeof(LNode));
assert(p != NULL);
p->val = val;
p->next = NULL;
return p;
}
void InitStack(LinkStack* slink) {
assert(slink != NULL);
slink->head = NULL;
slink->size = 0;
}
bool IsEmpty(LinkStack* slink) {
return slink->size == NULL;
}
bool Push(LinkStack* slink, int val) {
assert(slink != NULL);
LNode* p = CreatNode(val);
p->next = slink->head;
slink->head = p;
slink->size++;
return true;
}
bool Pop(LinkStack* slink) {
if (IsEmpty(slink)) {
return false;
}
else {
LNode* p = slink->head;
slink->head = p->next;
free(p);
return true;
}
}
bool GetTop(LinkStack* slink,int* pval) {
if (IsEmpty(slink)) {
*pval = 0;
return false;
}
else {
*pval = slink->head->val;
return true;
}
}
int GetSize(LinkStack* slink) {
return slink->size;
}
void ClearStack(LinkStack* slink) {
LNode* p = slink->head;
while (p->next != NULL) {
p->val = 0;
p = p->next;
}
}
void DestoryStack(LinkStack* slink) {
while (Pop(slink));
}
链式队列
定义
链式队列是一种队列,其元素使用链表结构存储,每个节点包含存储的数据和指向下一个节点的指针。链式队列的队首和队尾分别由链表的头节点和尾节点来表示。
特点
-
动态大小: 链式队列的大小(元素个数)可以根据需要动态调整,不像顺序队列有固定的容量限制。这使得链式队列可以灵活地处理不同规模的数据。
-
无需搬移元素: 在链式队列中进行入队和出队操作不需要搬移元素。在链表结构中,新元素的入队只需要简单地创建一个新节点,并更新队尾指针,而出队只需要将头节点移除,并更新队首指针。这使得链式队列的入队和出队操作的时间复杂度都是 O(1)。
-
内存动态管理: 链式队列通过动态分配和释放内存来管理队列的元素,可以更加灵活地利用内存资源,避免了静态数组可能出现的内存浪费问题。
-
容易扩展: 链式队列支持动态大小,当需要更多的空间时,可以很容易地添加新的节点来扩展队列。相比之下,顺序队列的扩展则需要重新分配更大的静态数组,并搬移现有元素,较为繁琐。
代码实现
节点描述
typedef struct LNode {
int val;
LNode* next;
}LNode;
队列描述
typedef struct LinkQueue {
LNode* head;
LNode* tail;
int size;
}LinkQueue;
初始化
void InitQueue(LinkQueue* queue) {
assert(queue!= NULL);
queue->head = queue->tail = NULL;
queue->size = 0;
}
创建节点
LNode* CreatLNode(int val) {
LNode* p = (LNode*)malloc(sizeof(LNode));
assert(p != NULL);
p->val = val;
p->next = NULL;
return p;
}
判空
bool IsEmpty(LinkQueue* queue) {
return queue->size == 0;
}
入队
bool PushQueue(LinkQueue* queue, int val) {
assert(queue != NULL);
LNode* p = CreatLNode(val);
if (queue->tail == NULL) {
queue->tail = queue->head = p;
}
else {
queue->tail->next = p;
queue->tail = p;
}
queue->size++;
return true;
}
出队
bool PopQueue(LinkQueue* queue) {
if (IsEmpty(queue)) {
return false;
}
else {
if (queue->size == 1) {
queue->tail = queue->head = NULL;
}
else
{
LNode* p = queue->head;
queue->head = p->next;
free(p);
}
queue->size--;
return true;
}
}
获取队首元素
bool GetHead(LinkQueue* queue, int* pval) {
if (IsEmpty(queue)) {
*pval = 0;
return false;
}
else {
*pval = queue->head->val;
return true;
}
}
获取队列中有效元素个数
int GetSize(LinkQueue* queue) {
return queue->size;
}
清空队列
void ClearQueue(LinkQueue* queue) {
LNode* p = queue->head;
while (p->next != NULL) {
p->val = 0;
p = p->next;
}
}
销毁队列
void DestoryQueue(LinkQueue* queue) {
while (PopQueue(queue));
}
完整代码
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
typedef struct LNode {
int val;
LNode* next;
}LNode;
typedef struct LinkQueue {
LNode* head;
LNode* tail;
int size;
}LinkQueue;
LNode* CreatLNode(int val) {
LNode* p = (LNode*)malloc(sizeof(LNode));
assert(p != NULL);
p->val = val;
p->next = NULL;
return p;
}
void InitQueue(LinkQueue* queue) {
assert(queue!= NULL);
queue->head = queue->tail = NULL;
queue->size = 0;
}
bool IsEmpty(LinkQueue* queue) {
return queue->size == 0;
}
bool PushQueue(LinkQueue* queue, int val) {
assert(queue != NULL);
LNode* p = CreatLNode(val);
if (queue->tail == NULL) {
queue->tail = queue->head = p;
}
else {
queue->tail->next = p;
queue->tail = p;
}
queue->size++;
return true;
}
bool PopQueue(LinkQueue* queue) {
if (IsEmpty(queue)) {
return false;
}
else {
if (queue->size == 1) {
queue->tail = queue->head = NULL;
}
else
{
LNode* p = queue->head;
queue->head = p->next;
free(p);
}
queue->size--;
return true;
}
}
bool GetHead(LinkQueue* queue, int* pval) {
if (IsEmpty(queue)) {
*pval = 0;
return false;
}
else {
*pval = queue->head->val;
return true;
}
}
int GetSize(LinkQueue* queue) {
return queue->size;
}
void ClearQueue(LinkQueue* queue) {
LNode* p = queue->head;
while (p->next != NULL) {
p->val = 0;
p = p->next;
}
}
void DestoryQueue(LinkQueue* queue) {
while (PopQueue(queue));
}