数据结构-基于双链表实现栈的基本操作

准备工作

#pragma once 
#include <stdlib.h>
//#include <stdio.h>

typedef char LinkStackType;
typedef struct LinkNode
{
      struct LinkNode* next;
      struct LinkNode* pre;
      LinkStackType data;
}LinkNode;
//创建节点
LinkNode* LinkStackCreat(LinkStackType value);
//初始化链表栈
void LinkStackInit(LinkNode** phead);
//打印栈
void LinkStackPrint(LinkNode*phead,char *s);
//入栈
void LinkStackPushBack(LinkNode*phead,LinkStackType value);
//出栈
void LinkStackPopBack(LinkNode* phead);
//销毁栈
void LinkStacDestory(LinkNode** phead);

下面是相关函数的实现

  • 栈的初始化

在初始化的时候,需要先创建新的节点,需要构造一个创建节点的函数,
初始化时将节点的数据区设置成0,注意这里是字符‘0’,因为重定义是就是定义的char型。这里可以灵活多变成你想要的类型。

初始化时,需要改变头结点的指向和数据区,所以需要传二级指针作为参数。
同样,销毁栈时,也需要传二级指针作为参数。

//创建一个节点
LinkNode * LinkStackCreat(LinkStackType value)
{
      LinkNode* newnode=(  LinkNode*)malloc(sizeof(LinkNode));
      newnode->data=value;
      newnode->next=newnode;
      newnode->pre=newnode;
      return newnode;
}

//初始化链表栈
void LinkStackInit(LinkNode** phead)
{
      if(  phead==NULL)
      {
           // printf(  "非法输入\n");
            return;
      }
      *phead=LinkStackCreat('0');
}

这里写图片描述
- 入栈
栈的特点是先进后出。所以采用尾插尾删的方法入栈,出栈。相关步骤在注释里

//打印栈
void LinkStackPrint(LinkNode*phead,char *s)
{

      if(  phead==NULL)
      {
           // printf(  "非法输入\n");
            return;
      }
      printf("%s\n",s);
      //从头到尾打印
      LinkNode*cur1=phead->next;
      for(  ;cur1!=phead;cur1=cur1->next)
      {
            printf("[%c][%p]    ",cur1->data,cur1);
      }
      printf("\n");
      //从尾到头打印
      //LinkNode*cur2=phead->pre;
      //for(  ;cur2!=phead;cur2=cur2->pre)
     // {
    //      printf("[%c][%p]    ",cur2->data,cur2);
      //}
     // printf("\n");

}

//入栈
void LinkStackPushBack(LinkNode*phead,LinkStackType value)
{

      if(phead==NULL)
      {
           // printf(  "非法输入\n");
            return;
      }
      LinkNode* newnode=LinkStackCreat(value);
      //找到尾节点
      LinkNode*tail=phead->pre;
      //tail vs newnode
      tail->next=newnode;
      newnode->pre=tail;
      //phead vs new
      phead->pre=newnode;
      newnode->next=phead;

}

这里写图片描述

  • 出栈
    采用尾删节点方法实现,删除时,需要销毁节点,所以需要构造一个删除节点的函数
//销毁节点
void LinkStackDestoryNode(LinkNode* to_delete)
{
      if(to_delete==NULL)
      {
            return;
      }
      free(to_delete);
}
//出栈
void LinkStackPopBack(LinkNode* phead)
{
      //非法输入
      if(phead==NULL)
      {
            return ;
      }
      //空栈
      if(phead->next==NULL)
      {
            printf(  "空栈\n");
            return ;
      }
      //找到要删除掉的节点
      LinkNode* to_delete=phead->pre;
      //找到要删除节点的前一个节点
      LinkNode* delete_before=to_delete->pre;
      //修改头指针指向
      phead->pre=delete_before;
      delete_before->next=phead;

      //销毁目标节点
      LinkStackDestoryNode( to_delete);

}

这里写图片描述
- 取栈顶元素

根据栈的特性:先进后出
最后一个入栈的元素,便是栈顶元素。取栈顶元素时可以通过一个输出性参数,将栈顶元素放在该参数的存储空间里。

还需要考虑栈是否为空的情况

//取栈顶元素
void LinkStackTop(LinkNode* phead,LinkStackType* value)
{

      //非法输入
      if(phead==NULL)
      {
            return ;
      }
      //空栈
      if(phead->next==NULL)
      {
            printf(  "空栈\n");
            return ;
      }
      //找到尾节点,取尾节点元素值
      LinkNode*tail=phead->pre;
      *value=tail->data;
}

这里写图片描述
- 销毁栈(这个现在我不太明白他的原理,后续更新)

//销毁栈
void LinkStacDestory(LinkNode** phead)
{
      //定义一个指针,初始化为NULL
      LinkNode* p=NULL;
      //如果头指针不为空,那么释放头指针
      //并且将下一个节点赋值给p

      while(*phead!=NULL)
      {
            p=(*phead)->next;
            free(*phead);
            if(p!=NULL)
            {
                  p->pre=NULL;

            }
            *phead=p;
      }
}

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值