数据结构第三章栈的基本操作


栈的介绍:

栈是一种只能在一端进行插入或者删除操纵的线性表或者链表,表中允许进行插入和删除操作的一端被称为栈顶,表的另外一端称为栈底
当栈中没有元素是称为空栈,栈的插入操作通常称为进栈或者入栈,栈的删除操作通常称为出栈或者退栈

栈的特点:

栈的特点是后进先出(Last In First Out,LIFO),即后进先出,后面进来的元素先出栈

栈的种类

采用线性存储结构的栈称为顺序栈,采用链式存储结构的被称为链式栈

栈的基本操作:

这里用的是链式栈,顺序栈在后面的文章中会仔细解释

//初始化栈
Status InitStack(LinkSqStack *Stack);
//销毁栈
Status DestoryStack(LinkSqStack *Stack);
//判空
Status EmptyStack(LinkSqStack *Stack);
//进栈
Status push(LinkSqStack *Stack,ElemType e);
//出栈
Status Pop(LinkSqStack *Stack,ElemType *e);
//取栈顶元素
Status GetPop(LinkSqStack *Stack,ElemType *e);
//将指针指向最后一个元素
Status pTail(LinkSqStack *Stack);
//求栈的长度
Status LengthStack(LinkSqStack *Stack);
//栈的遍历
Status TraverseStack(LinkSqStack *Stack);

栈的基本操作的实现:

状态常量
直接在头部定义以后后续改的时候方便,Status是int 的别名,也是为了后续改动方便

#include <stdlib.h>
#include <stdio.h>
#define OK  1
#define ERROR 0
#define OVERFLOW 2
#define TRUE 1
#define FALSE 0
typedef int Status;

栈的结构体定义
ElemType定义的是栈的节点的类型,取别名是为了后续方便改动

typedef int ElemType;
typedef struct LinkSqNode{
    ElemType data;
    struct LinkSqNode *next;
}LinkSqStack;

初始化栈
初始化栈过于简单,这里不做详细介绍

Status InitStack(LinkSqStack *Stack){
    Stack= (LinkSqStack*)malloc(sizeof(LinkSqStack));
    if (!Stack) {
        return FALSE;
    }
    Stack->next = NULL;
    return OK;
}

销毁栈
销毁栈,因为创建节点的时候是一个一个的创建的,所以销毁的时候也要一个一个的销毁,里面需要用到两个辅助指针,一个指针指向首元节点,一个指针指向首元节点的下一个节点,然后利用两个指针依次循环就可以销毁栈了,后面还要释放头节点

Status DestoryStack(LinkSqStack *Stack){
    LinkSqStack *p = Stack,*q = Stack->next;
    while (q) {
        p = q;
        q = q->next;
        free(p);
    }
    free(q);
    printf("栈已销毁\n");
    return OK;
}

栈的判空操作
如果头节点的后面为空,则栈空

Status EmptyStack(LinkSqStack *Stack){
    if (Stack->next == NULL) {
        printf("栈空\n");
        return FALSE;
    }else{
        printf("栈非空\n");
        return OK;
    }
}

进栈或入栈操作
一般用Push来表示入栈操作,创建一个新的节点,把要进栈的数据传给这个节点,再把这个节点插入到栈顶(这里的栈顶是在前面,以首元节点为栈顶,就是在链表的前端进行插入和删除操作)

Status push(LinkSqStack *Stack,ElemType e){
    LinkSqStack *p = (LinkSqStack*)malloc(sizeof(LinkSqStack));
    p->data = e;
    p->next = Stack->next;
    Stack->next = p;
    return OK;
}

出栈或者退栈操作
首先判断栈是否为空,然后用一个辅助指针移到首元节点上面,(注意:要先把值取出来才能进行删除节点),让头节点的指针域记录首元节点的指针域,然后释放首元节点

Status Pop(LinkSqStack *Stack,ElemType *e){
    if (Stack->next == NULL) {
        printf("栈空\n");
        return FALSE;
    }
    LinkSqStack *p;
    p = Stack->next;
    *e = p->data;
    Stack->next = p->next;
    free(p);
    return OK;
}

取栈顶元素
首先判断栈是否为空,然后不删除节点,直接取值就可以

Status GetPop(LinkSqStack *Stack,ElemType *e){
    if (Stack->next == NULL) {
        printf("栈空\n");
        return FALSE;
    }
        *e = Stack->next->data;
        return OK;
}

求栈的长度
操作过于简单,这里不做解释

Status LengthStack(LinkSqStack *Stack){
    int count = 0;
    while (Stack) {
        Stack = Stack->next;
        count++;
    }
    printf("栈的容量为%d",count);
    return OK;
}

栈的遍历
首先,要把指针移到首元节点上面,因为头节点不维护数据域,然后使用while循环遍历栈,直到指针指向栈底元素,栈底元素的指针域为空

Status TraverseStack(LinkSqStack *Stack){
    Stack = Stack->next;
    if (Stack->next == NULL) {
        printf("栈空\n");
        return FALSE;
    }
    while (Stack) {
        printf("%d\t",Stack->data);
        Stack =Stack->next;
    }
    return OK;
}

下面是栈的测试代码

int main(void){
    LinkSqStack Stack;
    ElemType e;
    InitStack(&Stack);
    for (int i = 0; i < 9; i++) {
        push(&Stack, i);
    }
    EmptyStack(&Stack);
    LengthStack(&Stack);
    printf("\n");
    TraverseStack(&Stack);
    printf("\n");
    GetPop(&Stack, &e);
    printf("栈顶元素%d",e);
    printf("\n");
    printf("元素出栈(前三个元素出栈)\n");
    for (int j = 0; j < 3; j++) {
        Pop(&Stack, &e);
        printf("%d\t",e);
    }
    printf("\n");
    DestoryStack(&Stack);
}

测试结果
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

所以我需要学这个吗?

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值