C语言版数据结构顺序栈的数据结构和基本操作函数实现

 这个简单程序的编写过程可谓不简单,一点小bug卡了将近10多天,今天灵感一来,解决了。

书上只有完整函数声明,但没有完整函数代码,于是我为了练习并且加深印象,就打算将所有函数实现一遍,于是就有了这个程序。在完成过程中有借鉴,但是有些借鉴并不正确,编译出来还是有错,我就自己再看书学习研究,根据自己的理解修改,最后费尽心思还是完成了这个练习程序代码,在Code::Blocks中顺利编译运行,真的是长舒了一口气,有些时候,需要缓缓,不要死磕,不然会很痛苦,放放再换个思路,可能就正确了。

在写代码过程中,收获最大的就是,对顺序栈的数据结构和基本操作函数理解更深了,也更清楚了,但还是差火候,需要经常巩固训练,不然会忘记,还没能达到刻在脑子里的熟练度。

要深深记住和理解&取地址符用的时机,啥时候该用啥时候不该用不需要用。

/**
此函数用来练习栈的顺序存储数据结构和基本操作函数实现
栈有栈底和栈顶base和top
Author:Cyan
Date:2018/10/10
**/
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>

#define STACK_INIT_SIZE 100//存储空间初始分配量
#define STACKINCREMENT 10//存储空间分配增量
typedef int sElemType;
typedef int Status;
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -1

//栈的ADT类型说明定义表示
typedef struct {
    sElemType *base;
    sElemType *top;
    sElemType  stacksize;
}sqStack ;

/*以下为栈的基本操作函数原型声明*/

//构造一个空栈
Status initStack(sqStack *);
//销毁栈S,S不再存在
Status destoryStack(sqStack *);
//把S置为空栈
Status clearStack(sqStack *);
//若栈为空栈,则返回TRUE,否则返回FALSE
Status emptyStack(sqStack );
//返回S的长度
sElemType stackLength(sqStack );
//若栈不空,则用e返回S栈顶的元素,并返回OK;否则返回ERROR
Status getTop(sqStack *, sElemType *);
//插入元素e为新的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
Status Push(sqStack *, sElemType );
//若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK,否则返回ERROR
Status Pop(sqStack *, sElemType *);
//从栈底到栈顶依次对栈中每个元素调用函数visit()。一旦visit()失败,则操作失败
Status stackTraverse(sqStack ,Status(*visit)());
//VISIT函数
Status visit(sElemType);


int main(void){

    sElemType i, j, k;
    Status a, b, c;
    sqStack S;
    printf("下面我们来初始化一个空栈吧!嘿嘿嘿\n");
    a = initStack(&S);

    if(a)
        printf("我们成功啦\n");

    b = emptyStack(S);

    if(!b)
        printf("是空栈没错\n\n");

    printf("下面准备输入\n");
    printf("打算输几个?\n");
    scanf("%d", &i);
    printf("好的,请输入%d个数\n",i);
    for(j = 0; j < i; j++){

        sElemType e;
        scanf("%d", &e);
        printf("你输入的第%d个数是%d\n", j + 1, e);
        c = Push(&S,e);
        if(c)
            printf("压栈成功\n");
    }

    j = stackLength(S);
    printf("此栈的长度为%d\n", j);


    printf("下面来测试stackTraverse()函数\n");
    stackTraverse(S,visit);

    sElemType e;
    printf("下面来测试getTop()函数\n");
    getTop(&S, &e);
    printf("栈顶的值为%d\n", e);


    printf("下面来测试Pop()函数\n");
    Pop(&S, &e);
    printf("删除的栈顶的值为%d\n", e);

    printf("下面我们来清空栈\n");
    Status s = clearStack(&S);
    if(s)
        printf("栈已成功清空\n");


    printf("下面我们来销毁栈\n");
    s = destoryStack(&S);
    if(s)
        printf("销毁成功\n");


    return 0;
}


/*以下是基本操作的算法描述*/

//构造一个空栈
Status initStack(sqStack *S){
    S->base = (sElemType*)malloc(STACK_INIT_SIZE * sizeof(sElemType));
    if(!S->base)
        exit (ERROR);
    S->top = S->base;
    S->stacksize = STACK_INIT_SIZE;

    return OK;
}
//销毁栈
Status destoryStack(sqStack *S){
    if(S->top == S->base)
        printf("是空栈,接下来继续销毁\n");

    S->top = NULL;
    S->stacksize = 0;
    free(S->base);

    return OK;
}
/*1->顺序栈的清空和销毁区别在哪?具体操作过程是怎样的?
2->清空栈只需修改栈顶指针吗?还需不需要将栈的大小置为0?
5->销毁栈是通过移动top指针依次释放每个节点,还是直接将栈顶指针和栈底
*/
//把S置为空栈
Status clearStack(sqStack *S){
    S->top = S->base;

    return OK;
}
//若栈为空栈,则返回TRUE,否则返回FALSE
Status emptyStack(sqStack S){
    if(S.base = S.top)
        return ERROR;
    else return TRUE;
}
//返回S的长度
sElemType stackLength(sqStack S){
    if((emptyStack(S)))
        exit(ERROR);

    return S.top - S.base;
}
//若栈不空,则用e返回S栈顶的元素,并返回OK;否则返回ERROR
Status getTop(sqStack *S, sElemType *e){
    if(S->top - S->base == 0)
       return ERROR;

    *e = *(S->top - 1);

    return OK ;
}
//插入元素e为新的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
Status Push(sqStack *S, sElemType e){

    if(S->top - S->base >= STACK_INIT_SIZE){
        S->base = (sElemType *)realloc(S->base, (S->stacksize + STACKINCREMENT) * sizeof(sElemType));//realloc函数的使用
        if(!S->base)
            return OVERFLOW;

        S->top = S->base + STACK_INIT_SIZE;
        S->stacksize = STACK_INIT_SIZE + STACKINCREMENT;
    }

        *S->top++ = e;
        printf("%d", e);
        printf("这数为%d\n", *(S->top - 1));

    return OK;
    }
//若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK,否则返回ERROR
Status Pop(sqStack *S, sElemType *e){
    if(S->top-S->base==0)
        return ERROR;

    *e = *(S->top - 1);//疑惑:弹栈时,是指针先减一还是先赋值给e
    S->top --;

    return OK;
}
//从栈底到栈顶依次对栈中每个元素调用函数visit()。一旦visit()失败,则操作失败
Status stackTraverse(sqStack S,Status(* visit)(sElemType)){// 函数指针?
    int *p, *n;
    int i;

    n = S.top;

    for( i = 0,p = S.base ; p < n ; p++, i++){
        Status s = visit(S.base[i]);
        if(!s)
            return ERROR;
    }
    printf("\n");


    return OK;
}
Status visit(sElemType e){

    printf("%d ", e);

    return OK;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值