官方给出的栈的定义是:
栈(stack)又名堆栈,它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
俗称“先进后出”。
接下来我们就用顺序表和链表来实现一个栈。
顺序表:
seqstack.h:
#pragma once
#include <stdio.h>
#include <stdlib.h>
typedef char DataType;
//定义栈的最大容量
#define seqstackMaxSize 100
#define LINE printf("----------------%s----------------\n",__FUNCTION__);
//栈的结构体
typedef struct seqstack{
DataType arr[seqstackMaxSize];
size_t size;
}seqstack;
void seqstackInit(seqstack* pstack);
void seqstackPush(seqstack* pstack,DataType value);
void seqstackPop(seqstack* pstack);
void seqstackDelete(seqstack* pstack);
DataType seqstackGetTop(seqstack* pstack);
seqstack.c:
#include "seqstack.h"
//初始化
void seqstackInit(seqstack* pstack)
{
if(pstack == NULL)
{
return;
}
pstack->size = 0;
}
//入栈
void seqstackPush(seqstack* pstack,DataType value)
{
if(pstack == NULL)
{
return;
}
//栈满了
if(pstack->size >= seqstackMaxSize)
{
printf("stack is full!\n");
return;
}
pstack->arr[pstack->size] = value;
++pstack->size;
}
//出栈
void seqstackPop(seqstack* pstack)
{
if(pstack == NULL)
{
return;
}
//空栈
if(pstack->size == 0)
{
printf("this stack is null!\n");
return;
}
--(pstack->size);
}
//销毁栈
void seqstackDelete(seqstack* pstack)
{
if(pstack == NULL)
{
return;
}
pstack->size = 0;
pstack = NULL;
}
//去栈顶元素
DataType seqstackGetTop(seqstack* pstack)
{
if(pstack == NULL)
{
return;
}
//空栈
if(pstack->size == 0)
{
printf("this is stack is null!\n");
return;
}
return pstack->arr[pstack->size - 1];
}
//----------------------------------------------------------------
//-----------测试函数
//----------------------------------------------------------------
//打印函数
void seqstackPrint(seqstack* pstack,char*msg)
{
if(pstack == NULL)
{
return;
}
printf("%s\n",msg);
printf(" 栈顶\n");
int i = pstack->size - 1;
for(;i >= 0;i--)
{
printf("[%c|%p]\n",pstack->arr[i],&(pstack->arr[i]));
}
printf(" 栈底\n");
}
void testseqstack()
{
LINE;
seqstack pstack;
seqstackInit(&pstack);
seqstackPush(&pstack,'a');
seqstackPush(&pstack,'b');
seqstackPush(&pstack,'c');
seqstackPush(&pstack,'d');
seqstackPush(&pstack,'e');
seqstackPrint(&pstack,"入栈5个");
LINE;
seqstackPop(&pstack);
seqstackPop(&pstack);
seqstackPrint(&pstack,"出栈2个");
LINE;
DataType cur = seqstackGetTop(&pstack);
printf("取栈顶元素\n");
printf("[%c]\n",cur);
}
int main()
{
testseqstack();
return 0;
}
运行效果图:
链表:
linkstack.h:
#pragma once
#include <stdio.h>
#include <stdlib.h>
#define LINE printf("-------------%s--------------\n",__FUNCTION__);
typedef char LinkType;
typedef struct linkstack{
LinkType data;
struct linkstack* next;
}linkstack;
void linkstackInit(linkstack** pstack);
linkstack* CreateNode(LinkType value);
void linkstackPush(linkstack** pstack,LinkType value);
void linkstackPop(linkstack** pstack);
void linkstackDelete(linkstack* pstack);
LinkType linkstackGetTop(linkstack* pstack);
linkstack.c:
#include "linkstack.h"
//初始化
void linkstackInit(linkstack** phead)
{
//因为我传的是二级指针,所以只需要判断phead是否合法即可,初始化只需把头指向空即可。
if(phead == NULL)
{
//非法输入
return;
}
*phead = NULL;
}
//创建节点
linkstack* CreateNode(LinkType value)
{
//切记malloc之后得写一个free
linkstack* new_node = (linkstack*)malloc(sizeof(linkstack));
if(new_node == NULL)
{
//malloc创建失败
perror("malloc");
return NULL;
}
new_node->next = NULL;
new_node->data = value;
return new_node;
}
//销毁节点free
void DeleteNode(linkstack* node)
{
free(node);
//为了指针的安全性,销毁完空间后,记得将指针指向空
node = NULL;
}
//入栈,相当与链表的头插
void linkstackPush(linkstack** phead,LinkType value)
{
if(phead == NULL)
{
//非法输入
return;
}
if(*phead == NULL)
{
//空栈,直接插入就行
*phead = CreateNode(value);
return;
}
linkstack* new_node = CreateNode(value);
if(new_node == NULL)
{
return;
}
new_node->next = *phead;
*phead = new_node;
}
//出栈,相当与链表的头删
void linkstackPop(linkstack** phead)
{
if(phead == NULL)
{
//非法输入
return;
}
if(*phead == NULL)
{
//已经是空栈了
return;
}
linkstack* to_delete = *phead;
*phead = (*phead)->next;
DeleteNode(to_delete);//记得销毁指针
}
//取得栈顶元素
LinkType linkstackGetTop(linkstack* phead)
{
if(phead == NULL)
{
//空栈
return 0;
}
return phead->data;
}
//-----------------------------------------------------------
//----------测试函数
//-----------------------------------------------------------
//打印函数
void linkstackPrint(linkstack* phead,char* msg)
{
if(phead == NULL)
{
//空栈
return;
}
printf("%s\n",msg);
printf(" 栈顶\n");
linkstack* cur = phead;
while(cur != NULL)
{
printf("[%c|%p]\n",cur->data,&(cur->data));
cur = cur->next;
}
printf(" 栈底\n");
}
void testlinkstackPush()
{
LINE;
linkstack* phead = NULL;
linkstackInit(&phead);
linkstackPush(&phead,'a');
linkstackPush(&phead,'b');
linkstackPush(&phead,'c');
linkstackPush(&phead,'d');
linkstackPush(&phead,'e');
linkstackPrint(phead,"入栈5个!");
}
void testlinkstackPop()
{
LINE;
linkstack* phead = NULL;
linkstackInit(&phead);
linkstackPush(&phead,'a');
linkstackPush(&phead,'b');
linkstackPush(&phead,'c');
linkstackPush(&phead,'d');
linkstackPush(&phead,'e');
linkstackPop(&phead);
linkstackPop(&phead);
linkstackPrint(phead,"出栈2个!");
}
void testlinkstackGetTop()
{
LINE;
linkstack* phead = NULL;
linkstackInit(&phead);
linkstackPush(&phead,'a');
linkstackPush(&phead,'b');
linkstackPush(&phead,'c');
linkstackPush(&phead,'d');
linkstackPush(&phead,'e');
linkstackPrint(phead,"取栈顶元素");
LinkType ch = linkstackGetTop(phead);
printf("栈顶元素:%c\n",ch);
}
int main()
{
testlinkstackPush();
testlinkstackPop();
testlinkstackGetTop();
return 0;
}
运行效果图: