!-- 顺序栈与链式栈的C语言实现 --!

基本操作:入栈、出栈、取栈顶元素
基本特性:先进后出

注意:栈本身不能遍历,不能打印,我们在代码中实现的打印只是为了检查代码的正确性

具体操作的详细解释在代码中会有注释。

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;
}

猜你喜欢

转载自blog.csdn.net/lycorisradiata__/article/details/79937005