准备工作
#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;
}
}