栈满足先进后出的功能,用于在很多场景,可以发挥意想不到的功能。
栈是一种特殊的线性表,因此可以通过线性链表来实现栈的功能。线性链表有顺序,和链式两种,这里选取链式链表实现栈(顺序请参考上一博客)。在链式链表实现栈模型,栈顶可以可以在链表的头部或尾部,用链表的尾部作为栈顶,入栈和出栈要遍历链表节点直到遍历到链表的尾部,过程复杂效率低下。但用链表的头部作为栈顶,入栈和出栈只用操作链表的首元素,不涉及到遍历链表,效率较高。因此,这里我们采用链表的头部做为栈顶。
详细讲解参照https://www.bilibili.com/video/av27904891/?p=1
本次使用工具为vs2017,作者水平有限,若有问题请指出。
栈头文件:Stack_Link_C.h
#pragma once
typedef void StackData;
typedef void Stack;
//定义栈节点数据类型
typedef struct StackNode
{
struct StackNode *Next;
StackData *data;
}StackNode;
//定义链表头
typedef struct StackHead
{
StackNode Head;
int StackLen;
}StackHead;
//创建栈
Stack *CreateStack();
//销毁栈
int DestoryStack(Stack **_stack);
//清除栈
int ClearStack(Stack *_stack);
//获取栈的元素个数
int GetStackLen(Stack *_stack);
//元素压入栈
int PushStack(Stack *_stack, StackData *_data);
//弹出元素
StackData *PopStack(Stack *_stack);
//获取栈顶元素
StackData *GetTopData(Stack *_stack);
栈源文件:Stack_Link_C.cpp
# include"pch.h"
# include"stdio.h"
# include"stdlib.h"
# include"Stack_Link_C.h"
//创建栈,返回栈的地址
Stack *CreateStack()
{
int ret = 0;
StackHead *stack = (StackHead *)malloc(sizeof(StackHead));
if (stack == NULL)
{
printf("Malloc Stack Head Error :CreateStack() \n");
}
stack->Head.Next = NULL;
stack->Head.data = NULL;
stack->StackLen = 0;
return (Stack *)stack;
}
//销毁栈
int DestoryStack(Stack **_stack)
{
int ret = 0;
if (_stack == NULL)
{
printf("Parameters is null :DestoryStack() \n");
ret = -1;
return ret;
}
//数据类型转换
StackHead **stack = (StackHead **)_stack;
StackNode *current = (*stack)->Head.Next; //current指向0号节点
StackNode *temp = (*stack)->Head.Next->Next; //temp指向1号节点
for (int i=0; i<(*stack)->StackLen-1; i++)
{
if (current != NULL)
{
free(current);
current = temp;
temp = current->Next;
}
}
(*stack)->Head.data = NULL;
(*stack)->Head.Next = NULL;
(*stack)->StackLen = 0;
*stack = NULL;
return ret;
}
//清除栈
int ClearStack(Stack *_stack)
{
int ret = 0;
if (_stack == NULL)
{
printf("Parameters is null :ClearStack() \n");
ret = -1;
return ret;
}
//数据类型转换
StackHead *stack = (StackHead *)_stack;
StackNode *current = (stack)->Head.Next; //current指向0号节点
StackNode *temp = (stack)->Head.Next->Next; //temp指向1号节点
for (int i = 0; i < (stack)->StackLen-1; i++)
{
if (current != NULL)
{
free(current);
current = temp;
temp = current->Next;
}
}
(stack)->Head.data = NULL;
(stack)->Head.Next = NULL;
(stack)->StackLen = 0;
return ret;
}
//获取栈的元素个数
int GetStackLen(Stack *_stack)
{
int ret = 0;
if (_stack == NULL)
{
printf("Parameters is null :GetStackLen() \n");
ret = -1;
return ret;
}
//数据类型转换
StackHead *stack = (StackHead *)_stack;
return stack->StackLen;
}
//元素压入栈
int PushStack(Stack *_stack, StackData *_data)
{
int ret = 0;
if (_stack == NULL || _data == NULL)
{
printf("Parameters is null :PushStack() \n");
ret = -1;
return ret;
}
//数据类型转换
StackHead *stack = (StackHead *)_stack;
StackData *data = (StackData *)_data;
StackNode *datacopy = (StackNode *)malloc(sizeof(StackNode)); //分配内存,把数据拷贝进来
if (datacopy == NULL)
{
printf("Malloc StackNode Error :PushStack() \n");
ret = -1;
return ret;
}
//拷贝数据
datacopy->data = data;
datacopy->Next = NULL;
if (stack->StackLen == 0) //空栈,第一次插入数据
{
stack->Head.Next = datacopy;
datacopy->Next = NULL;
stack->StackLen++;
}
else
{
datacopy->Next = stack->Head.Next;
stack->Head.Next = datacopy;
stack->StackLen++;
}
return ret;
}
//弹出元素
StackData *PopStack(Stack *_stack)
{
if (_stack == NULL)
{
printf("Parameters Error :PopStack() \n");
return NULL;
}
//数据类型转换
StackHead *stack = (StackHead *)_stack;
StackNode *data = NULL;
if (stack->StackLen <= 0)
{
printf("Stack hasn't element :PopStack() \n");
return NULL;
}
else if(stack->StackLen == 1) //只有一个元素
{
data = (StackNode *)stack->Head.Next->data;
stack->Head.Next = NULL; //头指针为NULL
stack->StackLen--;
}
else
{
data = (StackNode *)stack->Head.Next->data;
stack->Head.Next = stack->Head.Next->Next; //头指针指向1号节点
stack->StackLen--;
}
return data;
}
//获取栈顶元素
StackData *GetTopData(Stack *_stack)
{
if (_stack == NULL)
{
printf("Parameters Error :GetTopData() \n");
return NULL;
}
//数据类型转换
StackHead *stack = (StackHead *)_stack;
if (stack->StackLen <= 0)
{
printf("Stack hasn't element :GetTopData() \n");
return NULL;
}
return (StackData *)stack->Head.Next->data;
}
栈的测试源文件:Stack_Link_C_Test.cpp
# include"pch.h"
# include"stdio.h"
# include"stdlib.h"
# include"Stack_Link_C.h"
typedef struct stu
{
int age;
}stu;
//测试int型数据
void test1()
{
int a[] = { 1,2,3,4,5,6,7,8 };
int ret = 0;
int *data = NULL;
Stack *stack = CreateStack();
//压入元素
ret = PushStack(stack,(StackData *)a);
ret = PushStack(stack, (StackData *)(a + 1));
ret = PushStack(stack, (StackData *)(a + 2));
ret = PushStack(stack, (StackData *)(a + 3));
ret = PushStack(stack, (StackData *)(a + 4));
ret = PushStack(stack, (StackData *)(a + 5));
//弹出元素
printf("测试元素入栈和出栈 \n");
data = (int *)PopStack(stack);
printf("%d ",*data);
data = (int *)PopStack(stack);
printf("%d ", *data);
data = (int *)PopStack(stack);
printf("%d ", *data);
data = (int *)PopStack(stack);
printf("%d ", *data);
//获取栈顶元素
data = (int *)GetTopData(stack);
printf("%d ", *data);
//测试清空栈
printf("\n 测试清空栈再进栈出栈 \n");
ret = ClearStack(stack);
ret = PushStack(stack, (StackData *)(a + 6));
ret = PushStack(stack, (StackData *)(a + 6));
ret = PushStack(stack, (StackData *)(a + 7));
ret = PushStack(stack, (StackData *)a);
data = (int *)PopStack(stack);
printf("%d ", *data);
data = (int *)PopStack(stack);
printf("%d ", *data);
data = (int *)PopStack(stack);
printf("%d ", *data);
data = (int *)PopStack(stack);
printf("%d ", *data);
data = (int *)PopStack(stack);
if (data != NULL)
{
printf("%d ", *data);
}
//测试销毁栈
printf("\n 测试销毁栈 \n");
ret = PushStack(stack, (StackData *)(a + 7));
ret = PushStack(stack, (StackData *)a);
ret = PushStack(stack, (StackData *)(a + 7));
ret = PushStack(stack, (StackData *)a);
ret = DestoryStack(&stack);
ret = PushStack(stack, (StackData *)a);
}
//测试stu结构体
void test2()
{
stu a0,a1,a2,a3,a4,a5,a6,a7,a8,a9;
a0.age = 50;
a1.age = 51;
a2.age = 52;
a3.age = 53;
a4.age = 54;
a5.age = 55;
a6.age = 56;
a7.age = 57;
a8.age = 58;
a9.age = 59;
int ret = 0;
stu *data = NULL;
Stack *stack = CreateStack();
//压入元素
ret = PushStack(stack, (StackData *)(&a0));
ret = PushStack(stack, (StackData *)(&a1));
ret = PushStack(stack, (StackData *)(&a2));
ret = PushStack(stack, (StackData *)(&a3));
ret = PushStack(stack, (StackData *)(&a4));
ret = PushStack(stack, (StackData *)(&a5));
//弹出元素
printf("测试元素入栈和出栈 \n");
data = (stu *)PopStack(stack);
printf("%d ", data->age);
data = (stu *)PopStack(stack);
printf("%d ", data->age);
data = (stu *)PopStack(stack);
printf("%d ", data->age);
data = (stu *)PopStack(stack);
printf("%d ", data->age);
//获取栈顶元素
data = (stu *)GetTopData(stack);
printf("%d ", data->age);
//测试清空栈
printf("\n 测试清空栈再进栈出栈 \n");
ret = ClearStack(stack);
ret = PushStack(stack, (StackData *)(&a6));
ret = PushStack(stack, (StackData *)(&a6));
ret = PushStack(stack, (StackData *)(&a7));
ret = PushStack(stack, (StackData *)&a0);
data = (stu *)PopStack(stack);
printf("%d ", data->age);
data = (stu *)PopStack(stack);
printf("%d ", data->age);
data = (stu *)PopStack(stack);
printf("%d ", data->age);
data = (stu *)PopStack(stack);
printf("%d ", data->age);
data = (stu *)PopStack(stack);
if (data != NULL)
{
printf("%d ", data->age);
}
//测试销毁栈
printf("\n 测试销毁栈 \n");
ret = PushStack(stack, (StackData *)(&a7));
ret = PushStack(stack, (StackData *)&a0);
ret = PushStack(stack, (StackData *)(&a7));
ret = PushStack(stack, (StackData *)&a0);
ret = DestoryStack(&stack);
ret = PushStack(stack, (StackData *)&a0);
}
int main()
{
test1();
test2();
system("pause");
return 0;
}