1. 基本概念

栈是一种特殊的线性数据结构,它只允许在一端(通常是表尾)进行插入和删除操作,遵循后进先出(Last In First Out)的原则。
image-20250131233752946

栈的主要特点:

  • 后进先出(Last In First Out,简称LIFO)
  • 只在一端进行操作
  • 操作受限的线性表

基本概念:

  • 栈顶(Top):表尾位置,是数据插入和删除的唯一位置
  • 栈底(Base):表头位置
  • 入栈:将新元素添加到栈顶的操作
  • 出栈:从栈顶移除元素的操作

栈可以通过两种方式实现:

  • 顺序栈(数组实现)
  • 链式栈(链表实现)
    image-20250131233932327

时间复杂度分析:

  • 出栈操作:O(1)
  • 入栈操作:
    • 最好情况:O(1)
    • 最坏情况:O(n)(需要重新分配内存时)

2. 实现

image-20250131224324506

共五个程序文件 sqstack.h、linksatck.h、sqstack.c、linksatck.c、main.c , 包括了顺序栈和链式栈
sqstack.h

typedef int data_t;     // 定义数据类型  

typedef struct 
{
    data_t *data;
    int maxlen;           // 栈最大长度
    int top;             // 栈顶-1标准栈为空
} sqstack_struct,*sqstack;

sqstack sqstack_create(int length);       // 创建一个长度为length的栈,返回值为栈的指针
int sqstack_push(sqstack s, data_t x);     // 元素x入栈,返回值为 0表示成功,-1表示失败
int sqstack_empty(sqstack s);              // 判断栈是否为空,返回值为 1表示空,0表示非空
int sqstack_full(sqstack s);               // 判断栈是否为满,返回值为 1表示满,0表示非满
data_t sqstack_pop(sqstack s);             // 栈顶元素出栈,返回值为栈顶元素
data_t sqstack_top(sqstack s);             // 返回栈顶元素,栈顶元素不变
int sqstack_clear(sqstack s);              // 清空栈,返回值为 0表示成功,-1表示失败
int sqstack_free(sqstack s);               // 释放栈,返回值为 0表示成功,-1表示失败

linksatck.h

typedef int data_t; // 定义数据类型  

typedef struct node
{
    data_t data;        // 节点数据域
    struct node *next;  // 节点指针域
} linknode, *linkstack;

linkstack linkstack_create();               // 创建链栈,返回值 栈的地址
int linkstack_push(linkstack s, data_t x);  // 入栈,返回值 0-成功,1-失败
int linkstack_pop(linkstack s);             // 出栈,返回值 栈顶元素
int linkstack_empty(linkstack s);           // 判断栈是否为空,返回值 1-空,0-非空
// int linkstack_full(linkstack *s);  // 链栈动态存储,没有满这一说
data_t linkstack_top(linkstack s);          // 获取栈顶元素,返回值 栈顶元素
linkstack linkstack_free(linkstack s);      // 释放链栈,返回值NULL赋值给链栈

sqstack.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h> // for memset
#include "sqstack.h"

/**
  * @name 	sqstack_create()
  * @brief	创建顺序栈
  * @param  length	栈长
  * @retval 栈地址
  */
sqstack sqstack_create(int length)
{
    sqstack s;
    // 1. 检查栈长参数是否合理
    if (length < 0)
    {
        printf("length is invalid\n");
        return NULL;
    }
    // 2. 申请栈空间,先申请栈结构体,然后申请data空间
    if ((s = (sqstack)malloc(sizeof(sqstack_struct))) == NULL)
    {
        printf("malloc sqstack failed\n");
        return NULL;
    }
    if ((s->data = (data_t *)malloc(length*sizeof(data_t))) == NULL)
    {
        printf("malloc sqstack->data failed\n");
        free(s);
        return NULL;
    }

    // 3. 初始化栈
    memset(s->data, 0, length*sizeof(data_t));
    s->maxlen = length;
    s->top = -1;

    return s; 
}

/**
  * @name 	sqstack_push()
  * @brief	顺序栈入栈
  * @param  s 栈地址,x 入栈元素
  * @retval 0 入栈成功,-1 入栈失败
  */
int sqstack_push(sqstack s, data_t x)
{
    // 1. 检查栈是否存在以及栈是否满
    if (s == NULL)
    {
        printf("sqstack is invalid\n");
        return -1;
    }
    if (s->top == s->maxlen - 1)
    {
        printf("sqstack is full\n");
        return -1;
    }
    
    // 2. 入栈
    s->top++;
    s->data[s->top] = x;
    return 0;
}

/**
  * @name 	sqstack_empty()
  * @brief	顺序栈判断是否为空
  * @param  s 栈地址
  * @retval 0 栈为空,-1 栈不为空
  */
int sqstack_empty(sqstack s)
{
    // 1. 检查栈是否存在
    if (s == NULL)
    {
        printf("sqstack is invalid\n");
        return -1;
    }
    // 2. 通过栈顶判断栈是否为空
    return(s->top == -1 ? 1 : 0);    
}

/**
  * @name 	sqstack_full()
  * @brief	顺序栈判断是否满
  * @param  s 栈地址
  * @retval 0 栈为满,-1 栈不满
  */
int sqstack_full(sqstack s)
{
    // 1. 检查栈是否存在
    if (s == NULL)
    {
        printf("sqstack is invalid\n");
        return -1;
    }
    // 2. 通过栈顶判断栈是否为满
    return(s->top == s->maxlen - 1 ? 1 : 0);
}

/**
  * @name 	sqstack_pop()
  * @brief	顺序栈出栈
  * @param  s 栈地址
  * @retval 出栈元素
  */
data_t sqstack_pop(sqstack s)
{
    // 1. 检查栈是否存在
    if (s == NULL)
    {
        printf("sqstack is invalid\n");
    }
    // 2. 出栈
    s->top--;
    return s->data[s->top+1];
}

/**
  * @name 	sqstack_top()
  * @brief	顺序栈获取栈顶元素
  * @param  s 栈地址
  * @retval 出栈元素
  */
data_t sqstack_top(sqstack s)
{
    // 1. 检查栈是否存在
    if (s == NULL)
    {
        printf("sqstack is invalid\n");
    }
    // 2. 返回栈顶元素
    return s->data[s->top];
}

/**
  * @name 	sqstack_clear()
  * @brief	顺序栈清空
  * @param  s 栈地址
  * @retval 0 清空成功,-1 清空失败
  */
int sqstack_clear(sqstack s)  
{
    // 1. 检查栈是否存在
    if (s == NULL)
    {
        printf("sqstack is invalid\n");
        return -1;
    }
    // 2. 清空栈。直接将栈顶置为-1,后续的入栈操作会覆盖原来的值。
    s->top = -1;
    return 0;
}

/**
  * @name 	sqstack_free()
  * @brief	顺序栈出栈
  * @param  s 栈地址
  * @retval 0 释放成功,-1 释放失败
  */
int sqstack_free(sqstack s)
{
    if (s == NULL)
    {
        printf("sqstack is invalid\n");
        return -1;
    }
    if (s->data != NULL)
    {
        free(s->data);
    }
    free(s);
    return 0;
}

linkstack.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "linkstack.h"

/**
  * @name 	linkstack_create()
  * @brief	创建链式栈
  * @param  NULL
  * @retval 栈顶地址
  */
linkstack linkstack_create()
{
    // 1. 申请初始栈顶空间
    linkstack s = (linkstack)malloc(sizeof(linkstack));
    if ( s == NULL)
    {
        printf("malloc error\n");
        return NULL;
    }
    // 2. 赋值,初始化栈顶空间
    s->data = 0;
    s->next = NULL;

    return s;
}

/**
  * @name 	linkstack_push()
  * @brief	链式栈入栈
  * @param  s 栈顶地址, x 入栈元素
  * @retval 0 入栈成功,-1 入栈失败
  */
int linkstack_push(linkstack s, data_t x)
{
    // 1. 判断栈是否存在
    if (s == NULL)
    {
        printf("linkstack is invalid\n");
        return -1;
    }
    // 2. 申请新节点空间,并赋值,后续放置栈顶
    linkstack newcode = (linkstack )malloc(sizeof(linkstack));
    if ( newcode == NULL)
    {
        printf("newcode malloc error\n");
        return -1;
    }
    newcode->data = x;
    
    // 3. 将新节点放置栈顶(链表头部插入)
    newcode->next = s->next;
    s->next = newcode;
    return 0;
}

/**
  * @name 	linkstack_pop()
  * @brief	链式栈入栈
  * @param  s 栈顶地址
  * @retval 出栈元素
  */
int linkstack_pop(linkstack s)
{
    linkstack tem_node;
    data_t tem_value;
    // 1. 判断栈是否存在和栈是否为空
    if (s == NULL)
    {
        printf("linkstack is invalid\n");
        return -1;
    }
    if	(s->next == NULL)
    {
        printf("linkstack is NULL\n");
        return -1;
    }
    
    // 2. 将元素出栈
    tem_node = s->next;
    tem_value = tem_node->data;
    s->next = tem_node->next;

    // 3. 释放内存,返回出栈元素
    free(tem_node);
    tem_node = NULL;
    return	tem_value;
}
/**
  * @name 	linkstack_empty()
  * @brief	链栈判断是否为空
  * @param  s 栈地址
  * @retval 1 栈为空,0 栈不为空
  */
int linkstack_empty(linkstack s)
{
    if	(s == NULL)
    {
        printf("linkstack is invalid\n");
        return -1;
    }
    return (s->next == NULL ? 1 : 0);
}
/**
  * @name 	sqstack_top()
  * @brief	链栈获取栈顶元素
  * @param  s 栈地址
  * @retval 出栈元素
  */
data_t linkstack_top(linkstack s)
{
    // 1. 判断栈是否存在和栈是否为空
    if (s == NULL)
    {
        printf("linkstack is invalid\n");
        return -1;
    }
    if	(s->next == NULL)
    {
        printf("linkstack is NULL\n");
        return -1;
    }
    // 2. 返回栈顶元素
    return s->next->data;

}
/**
  * @name 	sqstack_free()
  * @brief	释放链栈
  * @param  s 栈地址
  * @retval NULL 赋值给栈地址
  */
linkstack linkstack_free(linkstack s)
{
    linkstack tem_node;

    if (s == NULL)
    {
        printf("linkstack is invalid\n");
        return NULL;
    }
    while (s != NULL)
    {
        tem_node = s;
        s = s->next;
        printf("free: %d\n", tem_node->data);
        free(tem_node);
    }

    return NULL;
}

main.c

#include <stdio.h>
#include <stdlib.h>
#include "sqstack.h"
#include "linkstack.h"

void test_sqstack();
void test_linkstack();

int  main(int argc, char *argv[])
{
    test_sqstack();
    test_linkstack();
    return 0;
}

void test_sqstack()
{
    sqstack s = sqstack_create(10);
    sqstack_push(s, 30);
    sqstack_push(s, 77);
    sqstack_push(s, 97);
    sqstack_push(s, 33);
    sqstack_push(s, 99);
    printf("top :%d\n", sqstack_top(s));
    while (!sqstack_empty(s))
    {
        printf("%d\n", sqstack_pop(s));
    }
    sqstack_free(s);
    printf("***SQSTACK TEST OVER****\n");
    return;
}

void test_linkstack()
{
    printf("\n");
    printf("***LINKSTACK TEST START****\n");
    linkstack s = linkstack_create();
    linkstack_push(s, 30);
    linkstack_push(s, 70);
    linkstack_push(s, 90);
    linkstack_push(s, 10);
    linkstack_push(s, 23);

    printf("top :%d\n", linkstack_top(s));

    while (!linkstack_empty(s))
    {
        printf("%d\n", linkstack_pop(s));
    }
    s = linkstack_free(s);
    return;
}
posted @ 2025-01-29 23:09  Arsun  阅读(16)  评论(0)    收藏  举报