顺序栈、链栈的基本操作

顺序栈元素‘"入栈":

比如,还是模拟栈存储 {1,2,3,4} 的过程。最初栈是"空栈",top 的值为 -1,如图1 所示:

图1 空栈示意图

 将元素 1 入栈,默认数组下标为 0 一端表示栈底,元素 1 存储在数组 a[0] 处,同时 top 值 +1,如图 2 所示:

图2 模拟栈存储元素 1

采用同样的方式,依次将元素 2、3 和 4 入栈,最终 top 的值变成 3,如图3 所示: 

图3 模拟栈存储{1,2,3,4}

因此,C 语言实现代码为:

//元素elem进栈,a为数组,top值为当前栈的栈顶位置
int push(int* a,int top,int elem){
    a[++top]=elem;
    return top;
}

代码中的 a[++top]=elem,等价于先执行 ++top,再执行 a[top]=elem。 

 顺序栈元素"出栈":

 实际上,top 变量的设置对模拟数据的 "入栈" 操作没有帮助,它是为实现数据的 "出栈" 操作做准备的。

比如,将图3 中的元素 2 出栈,则需要先将元素 4 和元素 3 依次出栈。需要注意的是,当有数据出栈时,要将 top 做 -1 操作。因此,元素 4 和元素 3 出栈的过程分别如图 6a) 和 6b) 所示: 

图 4数据元素出栈

 元素 4 和元素 3 全部出栈后,元素 2 才能出栈。因此,使用顺序表模拟数据出栈操作的 C 语言实现代码为:

//数据元素出栈
int pop(int * a,int top){
    if (top == -1) {
        printf("空栈");
        return -1;
    }
    printf("弹栈元素:%d\n",a[top]);
    top--;
    return top;
}

 代码中的 if 语句是为了防止用户做 "栈中已无数据却还要做出栈操作" 的错误操作。细心的读者还可能发现,出栈操作只是将 top 的值减 1,并没有像图 4 那样将出栈元素从数组中手动删除。这是因为,当有新的元素入栈后,新元素会将出栈元素覆盖掉,所以不删除出栈元素,也不会影响栈的正常使用,何必多此一举。

总结:

通过学习顺序表模拟栈中数据入栈和出栈的操作,初学者完成了对顺序栈的学习,这里给出顺序栈及对数据基本操作的 C 语言完整代码:

#include <stdio.h>
//元素elem进栈
int push(int* a, int top, int elem) {
    a[++top] = elem;
    return top;
}
//数据元素出栈
int pop(int* a, int top) {
    if (top == -1) {
        printf("空栈");
        return -1;
    }
    printf("弹栈元素:%d\n", a[top]);
    top--;
    return top;
}
int main() {
    int a[100];
    int top = -1;
    top = push(a, top, 1);
    top = push(a, top, 2);
    top = push(a, top, 3);
    top = push(a, top, 4);
    top = pop(a, top);
    top = pop(a, top);
    top = pop(a, top);
    top = pop(a, top);
    top = pop(a, top);
    return 0;
}

 程序输出结果为:

弹栈元素:4
弹栈元素:3
弹栈元素:2
弹栈元素:1
空栈

链栈元素入栈:

例如,依次将 1、2、3、4 存储到栈中,每个元素的入栈过程如图 1 所示:

 

图1 链栈元素依次入栈过程示意图

 C语言实现代码为:

//链表中的节点结构
typedef struct lineStack {
    int data;
    struct lineStack* next;
}LineStack;
//stack为当前的链栈,a表示入栈元素
LineStack* push(LineStack* stack, int a) {
    //创建存储新元素的节点
    LineStack* line = (LineStack*)malloc(sizeof(LineStack));
    line->data = a;
    //新节点与头节点建立逻辑关系
    line->next = stack;
    //更新头指针的指向
    stack = line;
    return stack;
}

 链栈元素出栈:

在图1) 所示链表的基础上,假设将元素 3 从栈中取出,根据"先进后出"的原则,要先将元素 4 出栈,然后元素 3 才能出栈,整个操作过程如图2 所示:

 

图 2 链栈元素出栈示意图

 实现栈顶元素出栈的 C 语言代码为:

//栈顶元素出链栈的实现函数
LineStack* pop(LineStack* stack) {
    if (stack) {
        //声明一个新指针指向栈顶节点
        LineStack* p = stack;
        //更新头指针
        stack = stack->next;
        printf("出栈元素:%d ", p->data);
        if (stack) {
            printf("新栈顶元素:%d\n", stack->data);
        }
        else {
            printf("栈已空\n");
        }
        free(p);
    }
    else {
        printf("栈内没有元素");
        return stack;
    }
    return stack;
}

 代码中通过使用 if 判断语句,避免了用户执行"栈已空却还要数据出栈"错误操作。

 总结:

本节,通过采用头插法操作数据的单链表实现了链栈结构,这里给出链栈及基本操作的C语言完整代码:

#include <stdio.h>
#include <stdlib.h>
//链表中的节点结构
typedef struct lineStack {
    int data;
    struct lineStack* next;
}LineStack;
//stack为当前的链栈,a表示入栈元素
LineStack* push(LineStack* stack, int a) {
    //创建存储新元素的节点
    LineStack* line = (LineStack*)malloc(sizeof(LineStack));
    line->data = a;
    //新节点与头节点建立逻辑关系
    line->next = stack;
    //更新头指针的指向
    stack = line;
    return stack;
}

//栈顶元素出链栈的实现函数
LineStack* pop(LineStack* stack) {
    if (stack) {
        //声明一个新指针指向栈顶节点
        LineStack* p = stack;
        //更新头指针
        stack = stack->next;
        printf("出栈元素:%d ", p->data);
        if (stack) {
            printf("新栈顶元素:%d\n", stack->data);
        }
        else {
            printf("栈已空\n");
        }
        free(p);
    }
    else {
        printf("栈内没有元素");
        return stack;
    }
    return stack;
}

int main() {
    LineStack* stack = NULL;
    stack = push(stack, 1);
    stack = push(stack, 2);
    stack = push(stack, 3);
    stack = push(stack, 4);
    stack = pop(stack);
    stack = pop(stack);
    stack = pop(stack);
    stack = pop(stack);
    stack = pop(stack);
    return 0;
}

 程序运行结果为:

弹栈元素:4 栈顶元素:3
弹栈元素:3 栈顶元素:2
弹栈元素:2 栈顶元素:1
弹栈元素:1 栈已空
栈内没有元素

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值