栈的链式存储API

来源:互联网 发布:一元夺宝app源码 编辑:程序博客网 时间:2024/05/24 06:31

栈,首先是一个线性表,也就是说,栈元素具有线性关系,即前驱后继关系。只不过它是一种特殊的线性表而已。它的特殊之处在于限制了线性表的插入和删除位置,它始终在栈顶进行,这就使得栈底是固定的,最先入栈的元素最后才能出栈。那么,我们根据栈的定义完全可以选用线性表进行模拟。我们知道线性表的实现由两种方式,即线性表顺序存储(顺序表)和线性表链式存储(链表)。在这里只能选用线性表的链式存储实现方式来模拟栈的链式存储,只不过我们只能选择头插法插入数据(相当于最最先入栈的元素排在栈底,以此类推)为什么选择头插法插入数据呢?或者这样有什么好处呢?假设我们选择尾插法入栈,当每次出栈的时候,我们会需要遍历整个链栈,浪费时间。如果我们采用头插法入栈,那么每次出栈的时候直接弹出头部结点即可,而不用遍历。这就是为什么我们选用链表头插法来模拟入栈的原因。当要弹出数据(出栈)是时,我们只需在链表头部弹出结点即可(相当于最后入栈的元素最先出栈)。我们按照栈的定义通过限制链表的插入操作和删除操作模拟了一个链栈。因此,我们借入之前在线性表的链式存储API这篇博文实现的程序基础上来模拟链栈的行为,将linklist.h和linklist.c加入工程并添加如下文件:

linkstack.h

#ifndef _MY_LINKSTACK_H_#define _MY_LINKSTACK_H_typedef void LinkStack;LinkStack* LinkStack_Create();void LinkStack_Destroy(LinkStack* stack);void LinkStack_Clear(LinkStack* stack);int LinkStack_Push(LinkStack* stack, void* item);void* LinkStack_Pop(LinkStack* stack);void* LinkStack_Top(LinkStack* stack);int LinkStack_Size(LinkStack* stack);#endif //_MY_LINKSTACK_H_

linkstack.c

#define _CRT_SECURE_NO_WARNINGS#include <stdlib.h>#include<stdio.h>#include <string.h>#include "linkstack.h"#include "linklist.h"typedef struct Teacher   {  LinkListNode listnode;  void *item;//栈 业务节点}Teacher;  /************************************************************************//*  链表的业务结点TLinkStackNode包含一个栈的业务节点                    *//*  这个结构体 是由Teacher 递推出来的                                   *//************************************************************************/typedef struct _tag_LinkStackNode   {  LinkListNode listnode;  void *item;//栈 业务节点}TLinkStackNode; //创建一个链栈 相当于创建一个链表LinkStack* LinkStack_Create(){return LinkList_Create();}/************************************************************************//*销毁一个链栈相等于销毁一个链表                                       *//*先清空 再销毁                                                        *//************************************************************************/void LinkStack_Destroy(LinkStack* stack){LinkStack_Clear(stack);LinkList_Destroy(stack);return;}/************************************************************************//*清空一个链栈 相等于清空一个链表                                       *//*但是 所有入栈的结点都是malloc出来的 (栈元素的生命周期管理)          *//*若要清空一个链栈 需要一个个弹出元素 并释放结点内存                    *//************************************************************************/void LinkStack_Clear(LinkStack* stack){if (stack==NULL){return;}while (LinkStack_Size(stack)>0){LinkStack_Pop(stack);//这个函数释放了结点内存}return;}/************************************************************************//*向链栈添加一个元素相当于向链表的头部插入元素(头插法?避免弹出元素遍历)*//*栈的 业务节点void* item  转换成链表的业务节点                         *//*所有入栈的元素都是malloc出来的                                        *//************************************************************************/int LinkStack_Push(LinkStack* stack, void* item){TLinkStackNode *tmp = NULL;int ret = 0;//对LinkList_Insert()而言 本函数LinkStack_Push()是主调函数 我们应该分配内存tmp =(TLinkStackNode*)malloc(sizeof(TLinkStackNode));memset(tmp,0,sizeof(TLinkStackNode));tmp->item = item;ret = LinkList_Insert(stack,(LinkListNode*)tmp,0);//头插法if (ret!=0){printf("func LinkStack_Push() err:%d\n",ret);if (tmp!=NULL){free(tmp);}return ret ;}return ret;}/************************************************************************//*从栈中弹出元素 相当于 从链表的头部删除元素                            *//*把链表的业务节点 转换成 栈的业务节点                                  *//*在LinkStack_Push()压栈的时,为栈结点分配了内存,所以弹出应该释放相应内存*//************************************************************************/void* LinkStack_Pop(LinkStack* stack){void*item= NULL;TLinkStackNode *tmp = NULL;tmp = (TLinkStackNode *)LinkList_Delete(stack,0);if (tmp==NULL){return NULL;}item = tmp->item;free(tmp);//释放内存return item;}//获取栈顶的元素 相当于获取链表的0号位置void* LinkStack_Top(LinkStack* stack){void*item= NULL;TLinkStackNode *tmp = NULL;tmp = (TLinkStackNode *)LinkList_Get(stack,0);if (tmp==NULL){return NULL;}item = tmp->item;return item;}//求栈的大小 相当于求链表的lenint LinkStack_Size(LinkStack* stack){return LinkList_Length(stack);}
test.c

#define _CRT_SECURE_NO_WARNINGS#include <stdlib.h>#include<stdio.h>#include <string.h>#include "linkstack.h"#include "linklist.h"int main(){LinkStack*stack = NULL;int i,a[10];stack = LinkStack_Create();if (stack ==NULL){return ;}//添加元素for (i=0;i<5;i++){a[i] = i+1;LinkStack_Push(stack,&a[i]);}//获取栈的基本属性printf("len:%d\n",LinkStack_Size(stack));printf("top:%d\n",*((int*)LinkStack_Top(stack)));//删除栈的元素while (LinkStack_Size(stack)>0){int *tmp;tmp = (int*)LinkStack_Pop(stack);printf("tmp:%d\n",*tmp);}LinkStack_Destroy(stack);system("pause");return 0;}



0 0
原创粉丝点击