栈
基本操作:入栈、出栈、取栈顶元素
基本特性:先进后出
注意:栈本身不能遍历,不能打印,我们在代码中实现的打印只是为了检查代码的正确性
具体操作的详细解释在代码中会有注释。
1.顺序栈:
在结构体内定义一个变量以
使用malloc申请内存,从而实现将顺序表的固定长度修改为可动态扩容
SeqStack.h
#pragma once
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#define SHOW_NAME printf("===================%s================\n",__FUNCTION__);
typedef char SeqStackType;
typedef struct SeqStack
{
SeqStackType* data;
size_t size;
size_t capacity;//data指向内存的最大容量,即顺序表中数组的MAXSIZE的替代品
}SeqStack;
SeqStack.c
#include "SeqStack.h"
void SeqStackInit(SeqStack* stack)//初始化
{
if(stack == NULL)
{
return;
}
stack->size = 0;
stack->capacity = 1000;//元素个数,而非内存字节数
stack->data = (SeqStackType*)malloc(stack->capacity * sizeof(SeqStackType));
return;
}
void SeqStackDestroy(SeqStack* stack)//销毁
{
free(stack->data);
stack->size = 0;
stack->capacity = 0;
return;
}
void SeqStackResize(SeqStack* stack)//扩容函数
{
if(stack == NULL)//双重保证
{
return;
}
if(stack->size < stack->capacity)
{
return;
}
stack->capacity = stack->capacity *2 +1;//扩容规则根据自己喜好定,这里+1是避免传入的capacity为0
//申请新内存
SeqStackType* new_ptr = (SeqStackType*)malloc(stack->capacity * sizeof(SeqStackType));
//将原来数据拷贝到新申请空间里(不推荐使用realloc)
size_t i = 0;
for(; i<stack->size; ++i)
{
new_ptr[i] = stack->data[i];
}
free(stack->data);//释放旧内存
stack->data = new_ptr;
return;
}
void SeqStackPush(SeqStack* stack, SeqStackType value)//元素进栈
{
if(stack == NULL)
{
return;
}
if(stack->size >= stack->capacity)//栈已满,需要扩容
{
SeqStackResize(stack);//调用扩容函数
}
stack->data[stack->size++] = value;
return;
}
void SeqStackPop(SeqStack* stack)//元素出栈
{
if(stack == NULL)
return;
if(stack->size == 0)//空栈
return;
stack->size--;//把最后一个元素置为无效即可
return;
}
int SeqStackGetTop(SeqStack* stack, SeqStackType* top)//取栈顶元素,返回两信息:是否取成功;用输出型参数top返回取得的栈顶元素
{
if(stack == NULL || top == NULL)
return 0;
if(stack->size == 0)
return 0;
*top = stack->data[stack->size-1];//这里不能写stack->size--,会改变size值
return 1;
}
void SeqStackPrint(SeqStack* stack,const char* msg)//打印栈内元素,为了检测释放入栈、出栈,实际上是不能打印栈的
{
printf("%s\n",msg);
if(stack == NULL)
return;
size_t i = 0;
for(; i<stack->size; ++i)
{
printf("[%c] ",stack->data[i]);
}
printf("\n");
return;
}
void TestInit()
{
SHOW_NAME;
SeqStack stack;
SeqStackInit(&stack);
printf("size : excepted is 0,actual is %d\n",stack.size);
printf("capacity : excepted is 1000,actual is %d\n",stack.capacity);
return;
}
void TestDestroy()
{
SHOW_NAME;
SeqStack stack;
SeqStackInit(&stack);
SeqStackDestroy(&stack);
return;
}
void TestPush()
{
SHOW_NAME;
SeqStack stack;
SeqStackInit(&stack);
SeqStackPush(&stack,'a');
SeqStackPush(&stack,'b');
SeqStackPush(&stack,'c');
SeqStackPush(&stack,'d');
SeqStackPush(&stack,'e');
SeqStackPush(&stack,'f');
SeqStackPrint(&stack,"入栈六个元素");
return;
}
void TestPop()
{
SHOW_NAME;
SeqStack stack;
SeqStackInit(&stack);
SeqStackPush(&stack,'a');
SeqStackPush(&stack,'b');
SeqStackPush(&stack,'c');
SeqStackPush(&stack,'d');
SeqStackPrint(&stack,"入栈六个元素");
SeqStackPop(&stack);
SeqStackPop(&stack);
SeqStackPrint(&stack,"出栈两个元素");
SeqStackPop(&stack);
SeqStackPop(&stack);
SeqStackPrint(&stack,"再出栈两个元素");
SeqStackPop(&stack);
SeqStackPrint(&stack,"再出栈一个元素");
return;
}
void TestGetTop()
{
SHOW_NAME;
SeqStack stack;
SeqStackInit(&stack);
SeqStackPush(&stack,'a');
SeqStackPush(&stack,'b');
SeqStackPush(&stack,'c');
SeqStackPush(&stack,'d');
SeqStackPush(&stack,'e');
SeqStackPush(&stack,'f');
SeqStackPrint(&stack,"入栈六个元素");
SeqStackType top;
int ret = SeqStackGetTop(&stack,&top);
if(ret == 1)
{
printf("获取栈顶元素成功,栈顶元素为 %c\n",top);
}
else
{
printf("获取栈顶元素失败\n");
}
return;
}
int main()
{
TestInit();
TestDestroy();
TestPush();
TestPop();
TestGetTop();
return 0;
}
2.链式栈:
利用与单链表类似的方法实现链式栈
LinkStack.h
#pragma once
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#define SHOW_NAME printf("\n===================%s================\n",__FUNCTION__);
typedef char LinkStackType;
//typedef struct LinkNode
//{
// LinkStackType data;
// LinkNode* next;
//}LinkNode;
typedef struct LinkStack//带头结点的链栈
{
LinkStackType data;
struct LinkStack* next;
}LinkStack;
LinkStack.c
#include "LinkStack.h"
LinkStack* CreateNode(LinkStackType value)//创建新结点
{
LinkStack* new_node = (LinkStack*)malloc(sizeof(LinkStack));
new_node->data = value;
new_node->next = NULL;
return new_node;
}
void LinkStackInit(LinkStack** stack)//初始化
{
*stack = NULL;
}
void LinkStackPush(LinkStack** stack,LinkStackType value)//元素入栈(尾插)
{
if(stack == NULL)
return;
if(*stack == NULL)//空栈
{
*stack = CreateNode(value);
return;
}
LinkStack* cur = *stack;
while(cur->next != NULL)
{
cur = cur->next;
}
LinkStack* new_node = CreateNode(value);
cur->next = new_node;
new_node->next = NULL;
return;
}
void DestroyNode(LinkStack* node)//销毁结点
{
free(node);//每一个malloc对应一个free
}
void LinkStackPop(LinkStack** stack)//元素出栈(尾删)
{
if(stack == NULL)//非法
return;
if(*stack == NULL)//空栈
return;
if((*stack)->next == NULL)//仅有一个元素
{
DestroyNode(*stack);
*stack = NULL;
return;
}
LinkStack* cur = *stack;
LinkStack* pre = NULL;//最后一个元素出栈后,还需将其next置空
while(cur->next != NULL)
{
pre = cur;
cur = cur->next;
}
pre->next = NULL;//链表的最后一个元素的next一定为NULL
DestroyNode(cur);
}
int LinkStackGetTop(LinkStack* stack,LinkStackType* top)//取栈顶元素(链表的最后一个元素)
{
if(stack == NULL || top == NULL)//空栈
return 0;
LinkStack* cur = stack;
while(cur->next != NULL)
{
cur = cur->next;
}
*top = cur->data;
return 1;
}
void LinkStackDestroy(LinkStack** stack)//销毁栈
{
if(stack == NULL)//非法操作
return;
if(*stack == NULL)
return;
LinkStack* cur = *stack;
while(cur != NULL)
{
LinkStack* to_delete = cur;
cur = cur->next;
DestroyNode(to_delete);
}
*stack = NULL;
}
void LinkStackPrint(LinkStack* stack,const char* msg)//打印栈中元素,检测一下代码是否正确
{
printf("[%s]\n",msg);
LinkStack* cur = stack;
while(cur != NULL)
{
printf("[%c] ",cur->data);
cur = cur->next;
}
printf("\n");
return;
}
void TestInit()
{
SHOW_NAME;
LinkStack* stack;
LinkStackInit(&stack);
}
void TestPush()
{
SHOW_NAME;
LinkStack* stack;
LinkStackInit(&stack);
LinkStackPush(&stack,'a');
LinkStackPush(&stack,'b');
LinkStackPush(&stack,'c');
LinkStackPush(&stack,'d');
LinkStackPush(&stack,'e');
LinkStackPrint(stack,"入栈五个元素");
}
void TestPop()
{
SHOW_NAME;
LinkStack* stack;
LinkStackInit(&stack);
LinkStackPush(&stack,'a');
LinkStackPush(&stack,'b');
LinkStackPush(&stack,'c');
LinkStackPush(&stack,'d');
LinkStackPrint(stack,"入栈五个元素");
LinkStackPop(&stack);
LinkStackPop(&stack);
LinkStackPrint(stack,"出栈两个元素");
LinkStackPop(&stack);
LinkStackPop(&stack);
LinkStackPrint(stack,"再出栈两个元素");
LinkStackPop(&stack);
LinkStackPrint(stack,"再出栈一个元素");
}
void TestGetTop()
{
SHOW_NAME;
LinkStack* stack;
LinkStackInit(&stack);
LinkStackPush(&stack,'a');
LinkStackPush(&stack,'b');
LinkStackPush(&stack,'c');
LinkStackPush(&stack,'d');
LinkStackPrint(stack,"入栈四个元素");
int ret = 0;
LinkStackType top;
ret = LinkStackGetTop(stack,&top);
if(ret == 1)
printf("取得栈顶元素为 %c\n",top);
else
printf("未取得栈顶元素\n");
LinkStackPop(&stack);
LinkStackPop(&stack);
LinkStackPrint(stack,"出栈两个元素");
ret = LinkStackGetTop(stack,&top);
if(ret == 1)
printf("取得栈顶元素为 %c\n",top);
else
printf("未取得栈顶元素\n");
LinkStackPop(&stack);
LinkStackPop(&stack);
LinkStackPrint(stack,"再出栈两个元素");
ret = LinkStackGetTop(stack,&top);
if(ret == 1)
printf("取得栈顶元素为 %d\n",top);
else
printf("未取得栈顶元素\n");
}
void TestDestroy()
{
SHOW_NAME;
LinkStack* stack;
LinkStackInit(&stack);
LinkStackDestroy(&stack);
}
int main()
{
TestInit();
TestPush();
TestPop();
TestGetTop();
TestDestroy();
return 0;
}