news 2026/6/10 22:26:51

用带头节点的链式存储实现栈的操作

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用带头节点的链式存储实现栈的操作

1.栈是一种只能在一端进行插入和删除的线性表

2.先构建一个数据类型,里面有next,data,top(可有可无)

typedef struct LNode { int top;//初始化的时候top等于-1,只有有数据就让top=1,这个数据项可有可无 struct LNode* next;//和单链表一样 int data;//数据域 }LNode,*LinkStack;//重命名

3.链栈的初始化

void InitStack(LinkStack* Ps) { (*Ps) = (LinkStack)malloc(sizeof(LNode));//创建头节点,不存放数据 if ((*Ps) == NULL) return; (*Ps)->next = NULL;//养成良好的习惯表尾置为空 (*Ps)->top = -1;//说明此时是没有元素的 }

4.从头节点进栈,这种时间复杂度比较高效,每次进栈时间复杂度为O(1)

int HeadPush(LinkStack* Ps, int elem)//前插 { LNode* s = (LNode*)malloc(sizeof(LNode));//和单链表一样 if (s == NULL) return 1; s->data = elem;//把数据赋值给新开辟的节点 s->next=(*Ps)->next;//把头节点的下一个元素赋值给s节点,就是把s的后驱链接到头节点的后驱 (*Ps)->next = s;//把头节点的后驱改为s,这样就把s节点给插入到表头的后面 s->top = 1;//可有可无 return 0; }

5.从头节点出栈,这种时间复杂度比较高效,每次出栈时间复杂度为O(1)

int HeadPop(LinkStack* Ps)//前删 { if ((*Ps)->next == NULL) { return 1; } LNode*temp=(*Ps)->next;//删除头节点的下一个节点 (*Ps)->next = temp->next;//把头节点的下一个节点指向下下个节点,跳过一个节点 if (temp->next = NULL) { (*Ps)->top = -1;//说明此时没有元素,可有可无 } free(temp);//因为是动态内存开辟的,是放在栈区的,需要手动释放 return 0; }

6.尾节点的进栈,可以一次性进栈也可以每次进栈一个元素。只需要找到最后一个非空的节点,在后面插入一个元素就可以了。

int TailPush(LinkStack* Ps)//这是一次性全部个建立好 { LNode* tail = (*Ps); int x = 0; scanf("%d", &x); while (x != 99)//等于99就不在建立 { LNode* s = (LNode*)malloc(sizeof(LNode)); if (s == NULL) return 1; s->next = tail->next; s->data = x; s->top = 1; tail->next = s; tail = s; scanf("%d", &x); } tail->next = NULL; return 0; }
int TailPush(LinkStack* Ps,int elem)//尾插法,这种办法有点笨,需要每次找到倒数第一个节点 { LNode* p = GetTail(Ps);//找到倒数第一个非空节点,然后在后面插入一个数据 LNode* s = (LNode*)malloc(sizeof(LNode)); if (s == NULL) { return 1; } s->next = p->next; p->next = s; s->top = 1; s->data = elem; return 0; }

7.尾节点出栈。需要找到倒数第二个元素,然后进行删除,当链表只有一个元素这种情况要考虑一下

int TailPop(LinkStack* Ps) { if (NULL == (*Ps)->next) return -1; if ((*Ps)->next->next == NULL)//如果这个链表只有一个元素 { LNode* ptr = (*Ps)->next; (*Ps)->next = ptr->next; free(ptr); return 0; } LNode* ptr = (*Ps); while (ptr->next->next)//链表有两个以上的元素 { ptr = ptr->next; } LNode* temp = ptr->next; ptr->next = temp->next; free(temp);//需要释放 }

8.得到栈顶元素,由于可以通过尾插法和头插法两种方式,所以分别对应一种方式

int Gettop(LinkStack* Ps)//头插法找top { if ((*Ps)->next == NULL) { return -1; } return (*Ps)->next->data;//既可以返回数据也可以判断是不是空链表 }//链式存储没有存满的
LNode* GetTail(LinkStack* Ps)//尾插法找top { LNode* p = (*Ps); while (p->next) { p = p->next; } return p;//是倒数最后一个指针 }

9.打印链表元素的函数

void Destory(LinkStack* Ps) { int ret = 0; while (ret!=1) { ret = HeadPop(Ps);//HeadPop出栈成功会返回0,空栈会返回1 } free(*Ps); }

10.整体函数

typedef struct LNode { int top;//初始化的时候top等于-1,只有有数据就让top=1,这个数据项可有可无 struct LNode* next;//和单链表一样 int data;//数据域 }LNode,*LinkStack;//重命名 void InitStack(LinkStack* Ps) { (*Ps) = (LinkStack)malloc(sizeof(LNode));//创建头节点,不存放数据 if ((*Ps) == NULL) return; (*Ps)->next = NULL;//养成良好的习惯表尾置为空 (*Ps)->top = -1;//说明此时是没有元素的 } int HeadPush(LinkStack* Ps, int elem)//前插 { LNode* s = (LNode*)malloc(sizeof(LNode));//和单链表一样 if (s == NULL) return 1; s->data = elem;//把数据赋值给新开辟的节点 s->next=(*Ps)->next;//把头节点的下一个元素赋值给s节点,就是把s的后驱链接到头节点的后驱 (*Ps)->next = s;//把头节点的后驱改为s,这样就把s节点给插入到表头的后面 s->top = 1;//可有可无 return 0; } int HeadPop(LinkStack* Ps)//前删 { if ((*Ps)->next == NULL) { return 1; } LNode*temp=(*Ps)->next;//删除头节点的下一个节点 (*Ps)->next = temp->next;//把头节点的下一个节点指向下下个节点,跳过一个节点 if (temp->next = NULL) { (*Ps)->top = -1;//说明此时没有元素,可有可无 } free(temp);//因为是动态内存开辟的,是放在栈区的,需要手动释放 return 0; } int TailPush(LinkStack* Ps)//这是一次性全部个建立好 { LNode* tail = (*Ps); int x = 0; scanf("%d", &x); while (x != 99)//等于99就不在建立 { LNode* s = (LNode*)malloc(sizeof(LNode)); if (s == NULL) return 1; s->next = tail->next; s->data = x; s->top = 1; tail->next = s; tail = s; scanf("%d", &x); } tail->next = NULL; return 0; } LNode* GetTail(LinkStack* Ps)//尾插法找top { LNode* p = (*Ps); while (p->next) { p = p->next; } return p;//是倒数最后一个指针 } int TailPush(LinkStack* Ps,int elem)//尾插法,这种办法有点笨,需要每次找到倒数第一个节点 { LNode* p = GetTail(Ps);//找到倒数第一个非空节点,然后在后面插入一个数据 LNode* s = (LNode*)malloc(sizeof(LNode)); if (s == NULL) { return 1; } s->next = p->next; p->next = s; s->top = 1; s->data = elem; return 0; } int TailPop(LinkStack* Ps) { if (NULL == (*Ps)->next) return -1; if ((*Ps)->next->next == NULL)//如果这个链表只有一个元素 { LNode* ptr = (*Ps)->next; (*Ps)->next = ptr->next; free(ptr); return 0; } LNode* ptr = (*Ps); while (ptr->next->next)//链表有两个以上的元素 { ptr = ptr->next; } LNode* temp = ptr->next; ptr->next = temp->next; free(temp);//需要释放 } void Display(LinkStack* Ps) { LNode* p = (*Ps)->next; while (p) { printf("%d->", p->data); p = p->next; } printf("NULL\n"); } int Gettop(LinkStack* Ps)//头插法找top { if ((*Ps)->next == NULL) { return -1; } return (*Ps)->next->data;//既可以返回数据也可以判断是不是空链表 }//链式存储没有存满的 void Destory(LinkStack* Ps) { int ret = 0; while (ret!=1) { ret = HeadPop(Ps);//HeadPop出栈成功会返回0,空栈会返回1 } free(*Ps); } int main() { LinkStack L; InitStack(&L); //HeadPush(&L, 1); //HeadPush(&L, 2); //HeadPush(&L, 3); //Display(&L); //HeadPop(&L); //HeadPop(&L); //HeadPop(&L); TailPush(&L,1); TailPush(&L, 1); TailPush(&L, 1); TailPush(&L,1); Display(&L); TailPop(&L); TailPop(&L); TailPop(&L); TailPop(&L); Display(&L); int ret=Gettop(&L); if (ret == -1) { printf("空链表\n"); } else { printf("%d\n", ret); } return 0; }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/9 21:14:11

WebLLM硬件加速终极指南:从零解决WebGPU兼容性问题

WebLLM硬件加速终极指南:从零解决WebGPU兼容性问题 【免费下载链接】web-llm 将大型语言模型和聊天功能引入网络浏览器。所有内容都在浏览器内部运行,无需服务器支持。 项目地址: https://gitcode.com/GitHub_Trending/we/web-llm 你是否曾经满怀…

作者头像 李华
网站建设 2026/6/10 17:48:16

如何优雅的应对屎山代码[特殊字符]

你眼中的 “烂代码”,或许曾支撑过公司的核心业务,甚至藏着你不知道的 “隐形坑”,就像是《左耳》里面写的:“前任也曾是爱的人”。 核心:职场不是 “写漂亮代码的乌托邦”,而是 “解决问题的修罗场”。 如…

作者头像 李华
网站建设 2026/6/10 17:35:29

基于Spring Boot+Vue的档案数字化项目管理系统

目录 项目介绍 演示视频 系统展示 代码实现 推荐项目 项目开发总结 为什么选择我 源码获取 博主介绍:✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领…

作者头像 李华
网站建设 2026/6/10 13:54:37

vue基于Spring Boot框架的宠物收养志愿者管理系统的设计与实现_0mp970vp

目录具体实现截图项目介绍论文大纲核心代码部分展示项目运行指导结论源码获取详细视频演示 :文章底部获取博主联系方式!同行可合作具体实现截图 本系统(程序源码数据库调试部署讲解)同时还支持java、ThinkPHP、Node.js、Spring B…

作者头像 李华
网站建设 2026/6/9 20:27:44

顶与底判断顶底 通达信指标 源码分享

{}VAR2:LLV(LOW,10); VAR3:HHV(HIGH,25); 我:3.5,COLOR0088FF; 清仓: 3.5,COLORYELLOW,LINETHICK3; 减仓: 3.2,COLORBLUE; 动力线: EMA((CLOSE-VAR2)/(VAR3-VAR2)*4,4); 强弱线:1.75,LINETHICK1,COLORGREEN; 关注:0.5,COLORBLUE ; {} 数值:动力线,COLORA8A8A8; DRAWBAND(减仓,R…

作者头像 李华
网站建设 2026/6/10 20:51:01

进销存软件哪个简单好用,3天学会进销存

第1天:理解核心概念与基础流程 进销存的主要模块: 进:采购订单、采购入库、采购退货 销:销售订单、销售出库、销售退货 存:库存盘点、库存报损、库存预警 软件基础操作: 入库:新增入库单&#x…

作者头像 李华