当前位置: 首页 > article >正文

【数据结构】C语言实现---栈

1、栈的概念与结构

栈:一种特殊的线性表,只允许在固定的一端进行插入和删除元素操作,进行数据插入和删除操作的一端称为栈顶另一端称为栈底栈中的数据元素遵守后进先出:LIFO(Last  in first  out)的原则。

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。

出栈:栈的删除操作叫做出栈。出数据在栈顶。

2、栈的实现

栈的实现方式:

(1)数组实现

(2)链表实现

栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一点。因为数组在尾上插入数据的代价比较小。

3、数组实现栈

声明:我是在vs2022中实现的。

Stack.h头文件

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdbool.h>
#include<stdlib.h>
typedef int  STDataType;
typedef struct Stack {
    STDataType* a;
    int top;
    int capacity;//栈的容量
}ST;
void    STInit(ST* pst);//栈初始化
void     STDestory(ST* pst);//栈的销毁
void    STPush(ST* pst,STDataType);//在栈顶插入数据
void    STPop(ST* pst);//在栈顶删除数据
bool    STEmpty(ST* pst);//判断栈是否为空
int  STSize(ST* pst);//求栈中数据元素个数
STDataType  STTop(ST* pst);//获取栈顶元素的值
 

Stack.c源文件

#include "Stack.h"
void   STInit(ST* pst)
{
    assert(pst);
    pst->a = NULL;
    pst->top = 0;//表示top指向栈顶元素的下一个位置
    pst->capacity = 0;

}
void   STDestory(ST* pst)
{
    assert(pst);
    free(pst->a);
    pst->a = NULL;
    pst->top = pst->capacity = 0;
}
void  STPush(ST* pst, STDataType x)
{
    if (pst->top == pst->capacity)
    {
        int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
        STDataType* tmp = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));
        if (tmp == NULL)
        {
            perror("realloc failed\n");
            return;

        }
        pst->a = tmp;
        pst->capacity = newcapacity;


    }
    pst->a[pst->top] = x;
    pst->top++;
}
STDataType    STTop(ST* pst)
{
    assert(pst);
    assert(!STEmpty(pst));
    return pst->a[pst->top - 1];
}

bool STEmpty(ST* pst)
{
    assert(pst);
    return pst->top == 0;
}
int STSize(ST* pst)
{
    assert(pst);
    return pst->top;
}
void  STPop(ST* pst)
{
    assert(pst);
    assert(!STEmpty( pst));
    pst->top--;


}


 

testStack.c源文件


#define  _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include "Stack.h"
void test()
{
    //初始化、进栈、出栈、取栈顶元素、判断栈是否为空、遍历
    ST  st;
    STInit(&st);//初始化;
    STPush(&st, 1);//插入数据
    STPush(&st, 2);//
    STPush(&st, 3);//
    STPush(&st, 4);//
    STPush(&st, 5);//
    printf("栈中元素个数:%d\n", STSize(&st));
    printf("栈顶元素数据为:%d\n", STTop(&st));
    //判断栈是否为空
    if (STEmpty(&st))
    {
        printf("栈为空\n");
    }
    else
    {
        printf("栈不为空\n");
    }
    遍历栈中元素:
    printf("栈中元素为:");
    while (!STEmpty(&st))
    {
        printf(" %d ", STTop(&st));
        STPop(&st);
    }
    printf("\n");
    STDestory(&st);
    printf("栈已经销毁");
}
int main()
{
    test();
    return 0;

}

通过在vs2022中,运行以上三个代码,则结果为:

4、单链表实现栈

单链表实现栈主体框架:

#define  _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
typedef  int ElemType;
typedef   struct Node
{
    ElemType  data;//数据域
    struct Node* next;//指针域

}Node;
typedef  struct LinkedStack
{
    Node* top;//栈顶指针
    int  size;//链栈的长度

}LinkedStack;
//初始化栈
void  initStack(LinkedStack* pstack)
{
    pstack->top = NULL;
        pstack->size = 0;
}
//判断栈是否为空
bool  isEmpty(LinkedStack stack)
{
    return stack.size == 0;
}
//求栈里面的元素个数
int  size(LinkedStack stack)
{
    return stack.size;
}
//实现入栈
void   push(LinkedStack* pstack, ElemType elem)
{
    Node* newnode = (Node*)malloc(sizeof(Node));
    if (newnode == NULL)
    {
        perror("内存溢出");
    }
    newnode->data = elem;
    //使用头插法把newnode插入到链表的头部(top)
    newnode->next = pstack->top;//指针域指向栈顶指针top
    pstack->top = newnode;
    pstack->size++;
    

}
//获取栈顶元素的数据域,并删除栈顶元素
ElemType  pop(LinkedStack* pstack)
{
    if (pstack->size == 0)
    {
        perror("栈是空的");
    }
    Node* poppedNode = pstack->top;//即将删除的链表首元结点
    ElemType poppedElem = poppedNode->data;
    pstack->top = pstack->top->next;
    free(poppedNode);//释放申请的内存
    return poppedElem;
}
//打印栈中的元素数据域(从栈顶到栈底)
void  printStack(LinkedStack stack)
{
    Node* temp = stack.top;
    while (temp != NULL)
    {
        printf("%d", temp->data);
        temp = temp->next;
    }
    printf("\n");
}
//获取栈顶元素,不删除
ElemType peek(LinkedStack stack)
{
    if (isEmpty(stack))
    {
        perror("栈是空的");
    }
    return stack.top->data;
}
void test()
{   
  //....

}
int main()
{
    test();
    return 0;
}

上面这个代码是单链表实现栈的框架,只需要在test()函数中,写具体的代码就可以了。

5、单链表实现栈的具体案例

将十进制转换为二进制:

代码:

#define  _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
typedef  int ElemType;
typedef   struct Node
{
    ElemType  data;//数据域
    struct Node* next;//指针域

}Node;
typedef  struct LinkedStack
{
    Node* top;//栈顶指针
    int  size;//链栈的长度

}LinkedStack;
//初始化栈
void  initStack(LinkedStack* pstack)
{
    pstack->top = NULL;
        pstack->size = 0;
}
//判断栈是否为空
bool  isEmpty(LinkedStack stack)
{
    return stack.size == 0;
}
//求栈里面的元素个数
int  size(LinkedStack stack)
{
    return stack.size;
}
//实现入栈
void   push(LinkedStack* pstack, ElemType elem)
{
    Node* newnode = (Node*)malloc(sizeof(Node));
    if (newnode == NULL)
    {
        perror("内存溢出");
    }
    newnode->data = elem;
    //使用头插法把newnode插入到链表的头部(top)
    newnode->next = pstack->top;//指针域指向栈顶指针top
    pstack->top = newnode;
    pstack->size++;
    

}
//获取栈顶元素的数据域,并删除栈顶元素
ElemType  pop(LinkedStack* pstack)
{
    if (pstack->size == 0)
    {
        perror("栈是空的");
    }
    Node* poppedNode = pstack->top;//即将删除的链表首元结点
    ElemType poppedElem = poppedNode->data;
    pstack->top = pstack->top->next;
    free(poppedNode);//释放申请的内存
    return poppedElem;
}
//打印栈中的元素数据域(从栈顶到栈底)
void  printStack(LinkedStack stack)
{
    Node* temp = stack.top;
    while (temp != NULL)
    {
        printf("%d", temp->data);
        temp = temp->next;
    }
    printf("\n");
}
//获取栈顶元素,不删除
ElemType peek(LinkedStack stack)
{
    if (isEmpty(stack))
    {
        perror("栈是空的");
    }
    return stack.top->data;
}
void test()
{   
    LinkedStack  linkedstack; 
    //初始化栈   //判断栈是否为空  //求栈里面的元素个数    //实现入栈    //获取栈顶元素的数据域,并删除栈顶元素
    //打印栈中的元素数据域(从栈顶到栈底)
    initStack(&linkedstack);
    int number = 0;
    printf("请输入要转换为二进制的十进制数字:");
        scanf("%d", &number);
        
        //while (num != 0)
        //{
        //    push(binaryStack, num % 2);        //余数入栈
        //    num /= 2;
        //}
        printf("十进制数字%d 转化为二进制数据为:", number);
        while (number  != 0)
        {
        
            push(&linkedstack , number%2);
            number /= 2;

        }
        printStack(linkedstack);

}
int main()
{
    test();
    return 0;
}

实验结果:


http://www.kler.cn/a/411787.html

相关文章:

  • 【Nginx】核心概念与安装配置解释
  • RPC学习
  • 【大数据学习 | Spark-Core】Spark的改变分区的算子
  • Windows系统电脑安装TightVNC服务端结合内网穿透实现异地远程桌面
  • 2024年11月25日Github流行趋势
  • Java面试之多线程并发篇
  • ChatGPT 4.0:如何提高学术论文的发表成功率
  • MATLAB深度学习(六)——LSTM长短期神经网络原理与应用
  • 华为ENSP--BGP路由协议实验详解
  • 网络安全期末复习
  • docker启动kafka、zookeeper、kafdrop
  • Oracle impdp-ORA-39083,ORA-00942
  • GitLab使用操作v1.0
  • 【设计模式】【行为型模式(Behavioral Patterns)】之策略模式(Strategy Pattern)
  • 【微服务架构】Kubernetes与Docker在微服务架构中的最佳实践(详尽教程)
  • 《免费学习网站推荐1》
  • 【JAVA】Java高级:Java网络编程——TCP/IP与UDP协议基础
  • 鸿蒙中拍照上传与本地图片上传
  • JavaWeb--JDBC
  • 如何搭建一个小程序:从零开始的详细指南
  • 过滤条件包含 OR 谓词,如何进行查询优化——OceanBase SQL 优化实践
  • C++设计模式-中介者模式
  • 【31-40期】从Java反射到SSO:深度解析面试高频问题
  • 17. 【.NET 8 实战--孢子记账--从单体到微服务】--记账模块--主币种设置
  • qt 读写文本、xml文件
  • 0 基础 入门简单 linux操作 上篇 利用apt命令装13 linux搭建自己的服务器