1. 创作灵感
在学习了链表之后,可以衍生出另外两个新的数据结构:栈(先进后出的线性表)、队列(先进先出的线性表)。通过几个简单的例子,实现栈和队列,提升数据结构的熟练程度
2. 栈的顺序存储结构及实现
通过数组存储数据,实现先进后出的效果。在实现的过程中要注意,初始化栈顶。
cpp
/*栈和队列*/
#define MAXSIZE 10
typedef int SElemType;
typedef struct
{
SElemType data[MAXSIZE];
int top; //栈顶
}SqStack;
//入栈
Status Push(SqStack* S, SElemType e)
{
if (S->top == MAXSIZE - 1)
{
return ERR;
}
S->top++;
S->data[S->top] = e;
return OK;
}
//出栈
Status Pop(SqStack *S, SElemType* e)
{
if (S->top == -1)
{
return ERR;
}
*e=S->data[S->top] ;
S->top--;
return OK;
}
int main()
{ //test
int a = 1, b = 2, c = 3;
int d, e, f;
SqStack MYStack;
MYStack.top = -1;
Push(&MYStack, a);
Push(&MYStack, b);
Push(&MYStack, c);
Pop(&MYStack, &d);
Pop(&MYStack, &e);
Pop(&MYStack, &f);
printf("%d,%d,%d\n", d, e, f);
return 0;
}
3. 栈的链式存储结构
有的时候栈内的元素的个数是不确定的,为了节约存储空间,我们使用链式结构存储栈,以下是链式栈的实现方式
3.1 链式栈的定义
cpp
//首先定义栈的一个节点
typedef struct StackNode
{
char name[30];//存储数据
struct StackNode* next;//指向下一个节点
}stacknode,*linkstackptr;
//定义一个结构体表示链式栈
typedef struct LinkStack
{
linkstackptr top;
int count;
}LinkStack;
3.2 入栈操作
cpp
//链站的入栈操作
Status Push(LinkStack* S, const char* e)
{
linkstackptr s = (linkstackptr)malloc(sizeof(stacknode));
strcpy_s(s->name,30,e);//将字符串保存到新节点的数据中
s -> next = S->top; //新节点的指向栈
S->top = s; //更新栈顶
S->count++;
return OK;
}
3.3 出栈操作
cpp
//链栈的出栈操作
Status Pop(LinkStack* S, char* e)
{
linkstackptr p;
strcpy_s(e, 30, S->top->name);
p = S->top;
S->top = S->top->next;
free(p);
S->count--;
return OK;
}
3.4 程序的调用
cpp
int main()
{ //test
LinkStack Mylinkstack;
char e1[30];
Push(&Mylinkstack, "zhang san");
Push(&Mylinkstack, "LI si");
Push(&Mylinkstack, "wang er");
Push(&Mylinkstack, "zhao liu");
Pop(&Mylinkstack, e1);
printf("%s\n", e1);
Pop(&Mylinkstack, e1);
printf("%s\n", e1);
Pop(&Mylinkstack, e1);
printf("%s\n", e1);
return 0;
}
运行结果:
从运行结果看实现了先进后出的顺序。

4.队列的链式结构
队列是为了实现先进先出(FIFO)顺序调用的线性表,在存储元素个数不确定的情况下,为了节约存储空间,同样适合使用链式存储结构去实现。
4.1 队列的定义以及初始化
cpp
//定义链式队列的一个节点
typedef struct QNode
{
char name[30];
struct QNode* next;
}Qnode, * Qnodeptr;
//定义链式队列
typedef struct
{
Qnodeptr front, rear;
}LinkQueue;
// 链式队列初始化函数
Status InitQueue(LinkQueue* Q)
{
// 为头节点分配内存
Q->front = Q->rear = (Qnodeptr)malloc(sizeof(Qnode));
if (!Q->front) // 检查头节点内存分配是否成功
{
printf("Queue init failed: malloc error!\n");
return ERR;
}
Q->front->next = NULL; // 头节点的next置空,队列初始为空
return OK;
}
4.2 尾部插入元素
cpp
/插入元素e在队尾
Status EnQueue(LinkQueue* Q, const char* e)
{
Qnodeptr s = (Qnodeptr)malloc(sizeof(Qnode));
if (!s)
printf("Error!\n");
strcpy_s(s->name, 30, e);//将字符串保存到新节点的数据中
s->next = NULL;
Q->rear->next = s;
Q->rear = s;
return OK;
}
4.3 队头取出元素
cpp
//出队
Status ExQueue(LinkQueue* Q, char* e)
{
Qnodeptr p;//定义一个节点的指针
if (Q->front == Q->rear)
return ERR;
p = Q->front->next;
strcpy_s(e, 30, p->name);
Q->front->next = p->next;
if (Q->rear == p)
Q->rear = Q->front;
free(p);
return OK;
}
4.4 测试调用
cpp
int main()
{
LinkQueue MyQueue;
char e1[30];
if (InitQueue(&MyQueue) != OK)
{
return -1; // 初始化失败,直接退出程序
}
EnQueue(&MyQueue, "Zhangsan");
EnQueue(&MyQueue, "Lisi");
EnQueue(&MyQueue, "Wanger");
EnQueue(&MyQueue, "Zhaoliu");
ExQueue(&MyQueue, e1);
printf("%s\n", e1);
ExQueue(&MyQueue, e1);
printf("%s\n", e1);
ExQueue(&MyQueue, e1);
printf("%s\n", e1);
return 0;
}
测试结果:
符合先进先出的顺序
