[数据结构]#4 用链表实现的栈结构
使用链表来实现栈是一种比较常见的做法,它能够有效利用链表的动态特性来支持栈的一些基本操作,例如:
1.Push(入栈):向栈中添加一个元素。
2.Pop(出栈):从栈中移除顶部的元素。
3.Peek/Top(查看栈顶元素):返回栈顶元素但不将其移除。
4.IsEmpty(判断栈是否为空):检查栈中是否有元素。
我们再来回忆一下链表,它由一系列节点组成,每个节点包含两部分:数据域和指针域(指向下一个节点)。对于单向链表来说,每个节点只有一个指向后续节点的链接。在链表的头部(head)是开始访问链表的入口点,在实现栈时,我们通常将链表头视为栈顶。
基于链表的代码结构,我们可以搭出这套用法的框架:
//linkstack.h文件#ifndef _LINKSTACK_H_
#define _LINKSTACK_H_typedef struct
{char name[32];char sex;int age;int score;
} DATATYPE;typedef struct stacknode
{DATATYPE data;struct stacknode* next;
} LinkStackNode;typedef struct
{LinkStackNode* top;int clen;
} LinkStack;LinkStack* CreateLinkStack();
int DestroyLinkStack(LinkStack* ls);
int PushLinkStack(LinkStack* ls, DATATYPE* data);
int PopLinkStack(LinkStack* ls);
int IsEmpytLinkStack(LinkStack* ls);
DATATYPE* GetTopLinkStack(LinkStack* ls);
int GetSizeLinkStack(LinkStack* ls);
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>//创建栈链表
LinkStack* CreateLinkStack()
{LinkStack* ls = malloc(sizeof(LinkStack));if (NULL == ls){fprintf(stderr, "CreateLinkStack malloc error\n");return NULL;}ls->top = NULL;ls->clen = 0;return ls;
}int GetSizeLinkStack(LinkStack* ls)
{return ls->clen;
}//获取栈顶数据
DATATYPE* GetTopLinkStack(LinkStack* ls)
{if (IsEmpytLinkStack(ls)){return NULL;}return &ls->top->data;
}//是否为空
int IsEmpytLinkStack(LinkStack* ls)
{return 0 == ls->clen;
}//释放内存
int DestroyLinkStack(LinkStack* ls)
{int size = GetSizeLinkStack(ls);for (int i = 0; i < size; i++){PopLinkStack(ls);}free(ls);return 0;
}
入栈、出栈:
//入栈
int PushLinkStack(LinkStack* ls, DATATYPE* data)
{LinkStackNode* newnode = malloc(sizeof(LinkStackNode));if (NULL == newnode){fprintf(stderr, "PushLinkStack malloc error\n");return 1;}memcpy(&newnode->data, data, sizeof(DATATYPE));newnode->next = NULL;if (IsEmpytLinkStack(ls)){ls->top = newnode;}else{newnode->next = ls->top;ls->top = newnode;}ls->clen++;return 0;
}//出栈
int PopLinkStack(LinkStack* ls) // head del
{if (IsEmpytLinkStack(ls)){return 1;}LinkStackNode* tmp = ls->top;ls->top = ls->top->next;free(tmp);ls->clen--;return 0;
}