news 2026/8/3 16:51:14

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

作者头像

张小明

前端开发工程师

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/8/2 0:27:08

物联网通信之CAN通讯

1.1CAN通讯介绍 参考:https://www.kvaser.cn/about-can/can-protocol-tutorial/ CAN(Controller Area Network 控制器局域网,简称CAN或者CAN bus)是一种功能丰富的车用总线标准。被设计用于在不需要主机(Host&#xff…

作者头像 李华
网站建设 2026/8/3 8:20:16

第二十九周 学习周报

摘要系统学习了ANSYS前处理工具链。几何方面,SCDM以直接建模见长,DM适合参数化设计。网格方面,Workbench Meshing易用高效;Fluent Meshing专业处理复杂流体网格;ICEM CFD则以高质量结构化网格著称。工具选择需权衡模型…

作者头像 李华
网站建设 2026/8/2 20:01:49

学习日记day8-面向对象实例

1.文字版格斗游戏JavaBean类 package Game;import java.util.Random;public class Role {private String name;private int blood;public Role(){}public Role(String name, int blood){this.name name;this.blood blood;}public String getName(){return name;}public void …

作者头像 李华
网站建设 2026/8/3 12:01:46

基于YOLOv8-Slimneck-WFU模型的苹果目标检测实现

1. 基于YOLOv8-Slimneck-WFU模型的苹果目标检测实现 1.1. 创新点 1、主干部分:使用了Focus网络结构,这个结构是在YoloV5里面使用到比较有趣的网络结构,具体操作是在一张图片中每隔一个像素拿到一个值,这个时候获得了四个独立的特…

作者头像 李华
网站建设 2026/8/3 6:01:22

python用openpyxl操作excel-sheet对象操作

python用openpyxl操作excel-sheet对象操作import logging import com.pro001.log.pro_log_config as pro_log_config from openpyxl import Workbook, load_workbook from openpyxl.styles import Font, Alignment, Side, PatternFill, Border import os import datetime impo…

作者头像 李华