数据结构栈(C语言版)

栈(Stack)是一种抽象数据类型(ADT),它体现了后进先出(Last In First Out, LIFO)的操作原则。

栈的基本概念

  1. 后进先出(LIFO):栈中的元素,最后被放入(push)的,最先被取出(pop)。
  2. 栈顶与栈底:栈有一个顶部和一个底部。栈顶是元素被插入和删除的那一端;栈底则是最老的元素所在的一端。

栈的物理实现

栈可以用数组或链表来实现:

  • 数组实现:使用一个固定大小的数组来存储栈元素,同时维护一个指向栈顶元素的指针。
  • 链表实现:使用链表节点来存储栈元素,每个节点包含数据和指向下一个节点的指针。栈顶指针指向链表的第一个节点。

栈的基本操作

以下为栈的主要操作:

  1. 初始化(Init):创建一个空栈。
  2. 入栈(Push):在栈顶插入一个新元素。
  3. 出栈(Pop):移除栈顶元素。
  4. 查看栈顶元素(Peek/Top):返回栈顶元素的值,但不移除它。
  5. 判断栈是否为空(IsEmpty):检查栈是否不包含任何元素。
  6. 判断栈是否满(IsFull):仅在固定大小的栈中需要,检查栈是否达到其容量限制。

     

栈的操作示例

以下是使用数组实现的栈的操作示例:

初始化
typedef struct Stack {
    int data[MAX_SIZE];
    int top;
} Stack;

void initStack(Stack *s) {
    s->top = -1; // 栈顶指针初始化为-1,表示栈为空
}
入栈
bool push(Stack *s, int value) {
    if (s->top == MAX_SIZE - 1) {
        // 栈满,无法入栈
        return false;
    }
    s->data[++s->top] = value; // 先移动栈顶指针,再插入元素
    return true;
}
出栈
bool pop(Stack *s, int *value) {
    if (s->top == -1) {
        // 栈空,无法出栈
        return false;
    }
    *value = s->data[s->top--]; // 先获取栈顶元素,再移动栈顶指针
    return true;
}
查看栈顶元素
bool peek(Stack *s, int *value) {
    if (s->top == -1) {
        // 栈空,无法查看栈顶元素
        return false;
    }
    *value = s->data[s->top];
    return true;
}
判断栈是否为空
bool isEmpty(Stack *s) {
    return s->top == -1;
}
判断栈是否满
bool isFull(Stack *s) {
    return s->top == MAX_SIZE - 1;
}

栈的应用

栈在计算机科学中有广泛的应用,以下是一些例子:

  • 函数调用:操作系统使用栈来管理函数调用,包括参数传递、返回值、局部变量等。
  • 表达式求值:编译器和解释器使用栈来解析和计算算术表达式。
  • 括号匹配:检查代码中的括号是否正确匹配。
  • 后退/撤销操作:在文本编辑器或其他应用程序中实现撤销操作。

栈的优缺点

优点

  • 插入和删除操作的时间复杂度为O(1),效率高。
  • 实现简单。

缺点

  • 栈的大小通常固定,使用数组实现时可能会导致空间浪费或不足。
  • 只能在栈顶进行操作,灵活性较低。

 代码示例

顺序栈
#include <stdio.h>
#include <stdlib.h>
typedef int data_t;
typedef struct seqstack
{
    int maxlen;   // 数组元素的总个数
    data_t *data; // 指向存放数据的数组的指针
    int top;      // 栈顶:最后一个有效元素的下标
} seqstack_t, *seqstack_p;

// 创建空顺序栈,len代表栈的最大长度
seqstack_p create_seqstack(int len)
{
    // 开辟顺序栈的结构体大小空间
    seqstack_p p = (seqstack_p)malloc(sizeof(seqstack_t));
    if (NULL == p)
    {
        perror("error");
        return NULL;
    }
    // 初始化结构体空间
    p->top = -1;
    p->maxlen = len;//保存数组的最大长度
    p->data = (data_t *)malloc(sizeof(data_t) * len);//开辟数组大小空间,单个元素大小乘以元素个数
    if (NULL == p->data)
    {
        perror("error");
        return NULL;
    }
    return p;
}

// 判满
int full_seqstack(seqstack_p p)
{
    return p->top + 1 == p->maxlen;
}

// 入栈
int push_seqstack(seqstack_p p, int data)
{
    if (full_seqstack(p))//判满
    {
        printf("push error");
        return -1;
    }
    else
    {
        p->top++;//让top栈顶加一
        printf("top:%d\n", p->top);
        p->data[p->top] = data;//让数据入栈
    }
    return 0;
}

// 判空
int empty_stack(seqstack_p p)
{
    return p->top == -1;
}

// 出栈
int pop_stack(seqstack_p p)
{
    if (empty_stack(p))//判空
    {
        printf("pop error");
    }
    while (p->top != -1)//栈顶有值,进入循环
    {
        printf("%d ", p->data[p->top]);//打印栈顶元素
        p->top--;//让栈顶减一
    }
    printf("\n");
}

// 遍历栈
int show(seqstack_p p)
{
    int i = 0;
    while (i <= p->top)
    {
        printf("%d ", p->data[i]);
        i++;
    }
    printf("\n");
}

int main(int argc, char const *argv[])
{
    seqstack_p p = create_seqstack(6);
    int i = 0, num;
    while (i < p->maxlen)
    {
        scanf("%d", &num);
        if (num == -1)
            break;
        else
        {
            push_seqstack(p, num);
        }
        i++;
    }
    show(p);
    pop_stack(p);
    return 0;
}
链式栈
#include <stdio.h>
#include <stdlib.h>
typedef int data_t;
typedef struct stacknode
{
    int data;
    struct stacknode *next;
} stacknode_t, *stacknode_p;

// 创建一个空链栈
void create_linkstack(stacknode_p *p) // p=&top   *p=top
{
    *p = NULL; // top=NULL
}

// 入栈:向栈中插入数据
int push_linkstack(stacknode_p *p, int data)
{
    stacknode_p new = (stacknode_p)malloc(sizeof(stacknode_t));//创建新节点
    if (NULL == new)
    {
        perror("error");
        return -1;
    }
    new->data = data;//将data放入新节点的数据域
    new->next = *p;//将新结点的插入到栈顶前面
    *p = new;//移动栈针到新的栈顶结点
    return 0;
}

// 出栈:删除栈中的元素
void pop_linkstack(stacknode_p *p)
{
    // 判空
    if (*p == NULL)
    {
        printf("empty");//如果栈中没有元素打印empty
    }
    else
    {
        while (*p != NULL)
        {
            stacknode_p del = *p;//让指针del指向栈顶节点  del=top
            *p = (*p)->next;//移动栈顶指针到下一个节点
            printf("%d\n", del->data);//打印出栈元素(要被删除的数据)
            free(del);//释放被删除节点
            del = NULL;
        }
    }
}

//计算栈的长度
int len_linkstack(stacknode_p p)
{
    int i = 0;
    while (p != NULL)
    {
        i++;
        p = p->next;
    }
    return i;
}

// 遍历栈中元素
void show_linkstack(stacknode_p p)
{
    if (p == NULL)
    {
        printf("empty");
    }
    else
    {
        while (p != NULL)
        {
            printf("%d ", p->data);
            p = p->next;
        }
    }
    printf("\n");
}

int main(int argc, char const *argv[])
{
    stacknode_p top;
    create_linkstack(&top);
    int i = 0, num;
    while (scanf("%d", &num) != EOF)
    {
        push_linkstack(&top, num);
    }
    show_linkstack(top);
    pop_linkstack(&top);
    show_linkstack(top);
    printf("len:%d\n",len_linkstack(top));
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值