首页 > 其他分享 >栈_单向链表

栈_单向链表

时间:2024-05-01 13:33:25浏览次数:27  
标签:结点 return Head 单向 QueueLList next 链表

利用单向链表设计一个栈,实现“后进先出”的功能

​ 栈内存自顶向下进行递增,其实栈和顺序表以及链式表都一样,都属于线性结构,存储的数据的逻辑关系也是一对一的。

​ 栈的一端是封闭的,数据的插入与删除只能在栈的另一端进行,也就是栈遵循“*后进先出*”的原则。也被成为“LIFO”结构,意思是“last input first output”。

闭合的一端被称为栈底(Stack Bottom),允许数据的插入与删除的一端被称为栈顶(Stack Top),不包含任何元素的栈被称为空栈。

  • l 把数据插入到栈空间的动作被称为入栈或者压栈,英文Push)
  • l 从栈空间中删除数据的动作被称为出栈或者弹栈,英文Pop)

程序结构思路:

​ 根据链表在头部增删比较简单的特性。将单向链表的首结点当作栈顶,尾结点当作粘底,入栈相当于头插操作,出栈相当于头删操作。

程序实现:

/********************************************************************************************
*   file name: StackLList.c
*   author   : liaojx2016@126.com
*   date     : 2024/04/25
*   function : Design stack interface to achieve “last input first output”
*   note     : None
*
*   CopyRight (c)  2023-2024   liaojx2016@126.com   All Right Reseverd 
*
*********************************************************************************************/
#include<stdio.h>
#include<string.h>
#include<stdbool.h>
#include<stdlib.h>
//指的是单向链表中的结点有效数据类型,用户可以根据需要进行修改
typedef int  DataType_t;

//构造链表的结点,链表中所有结点的数据类型应该是相同的
typedef struct StackLinkedList
{
	DataType_t  		 data; //结点的数据域
	struct StackLinkedList	*next; //结点的指针域

}QueueLList_t;

/**********************************************************************************************
*   func name       : QueueLList_Create
*   function        : Create a empty stack link list to store hexadecimal digit
*   func parameter  : None
*   return resuolt  : Address of head node
*   author          : liaojx2016@126.com
*   date            : 2024/04/25
*   note            : None
*   modify history  : None
*   function section: v1.0
*
**********************************************************************************************/
//创建一个空链表,空链表应该有一个头结点,对链表进行初始化
QueueLList_t * QueueLList_Create(void)
{
	//1.创建一个头结点并对头结点申请内存
	QueueLList_t *Head = (QueueLList_t *)calloc(1,sizeof(QueueLList_t));
	if (NULL == Head)
	{
		perror("Calloc memory for Head is Failed");
		exit(-1);
	}

	//2.对头结点进行初始化,头结点是不存储有效内容的!!!
	Head->next = NULL;

	//3.把头结点的地址返回即可
	return Head;
}
/**********************************************************************************************
*   func name       : StackLList_NewNode
*   function        : Create a new node and do initialization
*   func parameter  : 
*                       @data :address of head node 
*   return resuolt  : Address of a new node
*   author          : liaojx2016@126.com
*   date            : 2024/04/25
*   note            : None
*   modify history  : None
*   function section: v1.0
*
**********************************************************************************************/
//创建新的结点,并对新结点进行初始化(数据域 + 指针域)
QueueLList_t * QueueLList_NewNode(DataType_t data)
{
	//1.创建一个新结点并对新结点申请内存
	QueueLList_t *New = (QueueLList_t *)calloc(1,sizeof(QueueLList_t));
	if (NULL == New)
	{
		perror("Calloc memory for NewNode is Failed");
		return NULL;
	}

	//2.对新结点的数据域和指针域进行初始化
	New->data = data;
	New->next = NULL;

	return New;
}
/**********************************************************************************************
*   func name       : StackLList_Push
*   function        : Do stack push action
*   func parameter  : 
*                       @Head :address of head node 
                        @data :Disposed remainder
*   return resuolt  : Stack push success result (true or false)
*   author          : liaojx2016@126.com
*   date            : 2024/04/25
*   note            : None
*   modify history  : None
*   function section: v1.0
*
**********************************************************************************************/
//头插
bool StackLList_Push(QueueLList_t *Head,DataType_t data)

{
	//1.创建新的结点,并对新结点进行初始化
	QueueLList_t *New = QueueLList_NewNode(data);
	if (NULL == New)
	{
		printf("can not insert new node\n");
		return false;
	}
	//2.判断链表是否为空,如果为空,则直接插入即可
	if (NULL == Head->next)
	{
		Head->next = New;
		return true;
	}

	//3.如果链表为非空,则把新结点插入到链表的头部
	New->next  = Head->next;    //新结点的next指针指向原首结点
	Head->next = New;           //头结点的next指针指向新结点

	return true;
}
/**********************************************************************************************
*   func name       : StackLList_Pop
*   function        : Stack pop for one node
*   func parameter  : 
*                       @Head :address of head node 
*   return resuolt  : Stack pop success result (true or false)
*   author          : liaojx2016@126.com
*   date            : 2024/04/25
*   note            : None
*   modify history  : None
*   function section: v1.0
*
**********************************************************************************************/
//头删
bool StackLList_Pop(QueueLList_t *Head)
{
    //当链表为空,删除失败,返回false
    if (NULL == Head->next)
	{
		printf("Stack linklist is empty,headdelete failed\n");
		return false;
	}
    QueueLList_t *Delnode=Head->next;   //备份首结点
    //printf("next=%#x\n",Head->next->next);
    //输出出栈的数据
    printf("the push element data is %d\n",Head->next->data);
    //删除出栈结点
    Head->next=Head->next->next;    //头结点的next指针指向首结点的直接后继
    Delnode->next=NULL;             //原首结点指向NULL,防止内存泄漏
    free(Delnode);                  //释放内存
    return true;
}
/**********************************************************************************************
*   func name       : QueueLList_Print
*   function        : Stack data print
*   func parameter  : 
*                       @Head :address of head node 
*   return resuolt  : Print success result (true or false)
*   author          : liaojx2016@126.com
*   date            : 2024/04/25
*   note            : None
*   modify history  : None
*   function section: v1.0
*
**********************************************************************************************/
//遍历
bool QueueLList_Print(QueueLList_t *Head)
{
    if (Head->next==NULL)   {
        printf("stack link list is empty\n");
        return false;
    }
	//对链表的头文件的地址进行备份
	QueueLList_t *Phead = Head;
	printf("the Stack linkedlist data is \n");
    //遍历结点,输出数据
	do
	{
		//把头的直接后继作为新的头结点
		Phead = Phead->next;
		//输出头结点的直接后继的数据域
		printf("%d ",Phead->data);
	}
	while(Phead->next);
    printf("\n");
    return true;
}
//
int main(int argc, char const *argv[])
{
	QueueLList_t *head=QueueLList_Create();
    //StackLList_Push 入栈操作,StackLList_Pop 出栈操作,QueueLList_Print 栈遍历输出
    StackLList_Push(head,0);
    QueueLList_Print(head);
    StackLList_Pop(head);
    QueueLList_Print(head);
    StackLList_Push(head,1);
    StackLList_Push(head,6);
    StackLList_Push(head,4);
    QueueLList_Print(head);
    StackLList_Pop(head);
    QueueLList_Print(head);

	return 0;
}

测试输出结果:
image

标签:结点,return,Head,单向,QueueLList,next,链表
From: https://www.cnblogs.com/JinBool/p/18169268

相关文章

  • 力扣-203. 移除链表元素
    1.题目题目地址(203.移除链表元素-力扣(LeetCode))https://leetcode.cn/problems/remove-linked-list-elements/题目描述给你一个链表的头节点head和一个整数val,请你删除链表中所有满足Node.val==val的节点,并返回新的头节点。 示例1:输入:head=[1,2,6,3,4,5,......
  • 链表逆序
    数据结构链表逆序笔试题:编写一个函数,实现单链表逆序代码//方法一:将尾结点循环插到头节点后面,实现逆序voidreverse_list(single_list*head){single_list*p=head->next;//将链表除头节点的节点保存head->next=NULL;//将链表断开single_list*tmp=......
  • 双向链表
    双向链表接口设计//指的是双向链表中的结点有效数据类型,用户可以根据需要进行修改typedefintDataType_t;//构造双向链表的结点,链表中所有结点的数据类型应该是相同的typedefstructDoubleLinkedList{ DataType_tdata; //结点的数据域 structDoubleLinkedList......
  • 双向循环链表队列的接口设计
    /***************************************************filename:DoubleLinkQueue.c*author:momolyl@126.com*date:2024/04/28*brief:构建双向循环链队的接口*note:None**CopyRight(c)2024momolyl@126.comAllRigh......
  • 链表
    P1996约瑟夫问题动态链表临时分配链表节点,使用完毕后释放链表节点。优点:能及时释放空间,不使用多余内存缺点:需要管理空间,容易出错。#include<bits/stdc++.h>#defineintlonglong#definerep(i,a,b)for(inti=(a);i<=(b);++i)#definefep(i,a,b)for(int......
  • 双向循环链表接口设计
    /***************************************************filename:DoubleDoubleCirLkList.c*author:momolyl@126.com*date:2024/04/25*brief:通过构建双向循环链表学习顺序存储*note:None**CopyRight(c)2024momolyl@126......
  • 链表逆序
    编写一个函数,实现单链表逆序,,函数原型如下:*voidreverse_list(single_listhead)程序代码如下:voidreverse_list(single_list*head){single_list*p=head->next;//将链表除头节点的节点保存head->next=NULL;//将链表断开single_list*tmp=NULL;while(......
  • 单向循环链表接口设计
    目录单向循环链表接口设计创建新的头结点创建新节点并初始化该节点工具函数遍历链表查找尾结点查找尾结点前置驱动找到指定结点查找指定节点前置驱动创建每一个新节点并插入到头部新建结点并插入到尾部新建结点并插入到指定节点之后删除头部结点删除尾部结点删除指定结点调试函数......
  • 双向循环链表的头插法的实现
    include<stdio.h>include<stdlib.h>typedefstructslik{intdata;structslik*next;structslik*prev;}sli;voidcreatesli(sli**head,inta[],intsize){for(inti=0;i<size;i++){sli*s=(sli*)malloc(sizeof(sli));s->data=a[i];......
  • 单向循环链表的头插法实现
    ``#include<stdio.h>``````include<stdlib.h>typedefstructslik{intdata;structslik*next;}sli;voidcreatesli(sli**head,inta[],intsize){for(inti=0;i<size;i++){sli*s=(sli*)malloc(sizeof(sli));s->data=a[i];s->......