c语言实现栈基本操作

栈的基础操作的两种实现方法

1. 定义结构体来构建栈

  • 链表实现

    typedef struct stack{
        int element;
        struct stack *next;
    }NODE,*Stack;
    

    用指针去连接各个结点

  • 数组实现

    typedef struct stack{
        int Capacity;//可放结点的容量
        int topofStack;//数组元素的角标
        int *Array;///指向数组首元素地址的指针
    }NODE,*Stack;
    

让数组去存储栈中的各个值,相当于定义了一个Capacity长度的数组Array,通过topofStack来访问数组中的元素

2. 创建栈头createStack

  • 链表实现

    Stack createStack(){
        Stack s=(Stack)malloc(sizeof(NODE));
        assert(s);
        s->next=NULL;
        return s;
    }
    

    不需要去为头结点做数据的初始化

  • 数组实现

    Stack createStack(int maxNumber){
        if(maxNumber<5){
            printf("too small");
            return NULL;
        }
        Stack s=(Stack)malloc(sizeof(NODE));
        assert(s);
        s->Array=(int)malloc(sizeof(int)*maxNumber);
        assert(s->Array);
        s->Capacity=maxNumber;
        s->topofStack=-1;//这里将数组角标设为-1,当出现带有数据的结点时数组角标会增加
        return s;
    }
    
    • 数组实现最不方便的一点就是需要提前指定最大容量,不能像链表实现那样随意
    • 当然为了避免错误容量的出现,可以设定一个最小容量值与要分配的大小作对比
    • 数组实现内部还有一个数组也需要进行内存申请,所以要分配两次

3. 判断是否为空

  • 链表实现

    int isEmpty(Stack s){
        return s->next==NULL;
    }
    

    直接判断头结点的下一个是否为空即可

  • 数组实现

    int isEmpty(Stack s){
        return s->topofStack==-1;
    }
    

    如果时头结点那么数组下标将会是-1,即空

3. 压栈push

  • 链表实现

    void push(int n,Stack s){
        Stack node;
        node=(Stack)malloc(sizeof(NODE));
        assert(node);
        node->element=n;
        node->next=s->next;
        s->next=node;
    }
    

    和常规的链表从头部增加结点一样,因为是单指针,原本表头和下一个结点连的那条线要后断

  • 数组实现

    int isFull(Stack s){
        return s->Capacity==s->topofStack+1;
    }//数组内元素数量和角标的关系
    void push(int n,Stack s){
        if(isFull(s)){
            printf("there is a error!\n");
            return;
        }
        s->Array[++s->topofStack]=n;
        //不看括号内的内容,就是正常的给数组元素赋值,而++使数组移向下一个元素
        //++结合的优先级低于->,所以是对topofStack进行++的操作
    }
    

    正如第二点对于数组缺陷描述的那样,不能随意增加结点,数组实现是有最大长度的

4. 出栈pop

  • 链表实现

    void pop(Stack s){
        if(isEmpty(s)){
            printf("there is a false\n");
            return;
        }
        Stack node=s->next;
        s->next=node->next;
        free(node);
    }
    

    就是常规的从头部删除节点,定义一个临时结点去操作
    虽然没有分配堆区内存,但最好还是free一下

  • 数组实现

    void pop(Stack s){
        if(isEmpty(s)){
            printf("there is a error!\n");
            return;
        }
        s->topofStack--;
        //和push时一样,--的优先级低于->
    }
    

    数组的优势展现,再加下一个结点时只需要覆盖原来的值就好了,所以出栈让其数组元素下标减少就好了,不用像链表那样定义临时节点

5. 查看栈顶元素top

  • 链表实现

    int top(Stack s){
        if(!isEmpty(s)){
            return s->next->element;
        }
        printf("there is a error\n");
        return 0;
    }
    
  • 数组实现

    int top(Stack s){
        if(!isEmpty(s)){
            return s->Array[s->topofStack];
        }//引用链表的下标时不要忘了用s->
        printf("there is a error!\n");
        return 0;
    }
    

6. 销毁栈

  • 链表实现
void destroy(Stack s){
    Stack pmove=s->next;
    while(pmove!=NULL){
        free(s);
        s=pmove;
        pmove=pmove->next;
    }
    free(s);
}
  • 数组实现

    void Disposestack(Stack s){
        if(s!=NULL){
            free(s->Array);
            free(s);
        }
    }
    

    数组实现的直接释放数组就好了,但是别忘了动态分配了两次,所以要释放两次

7. 打印栈printStack

  • 链表实现

    void printStack(Stack s){
        Stack pmove;
        assert(pmove);
        pmove=s->next;
        while(pmove!=NULL){
            printf("the element is %d\n",pmove->element);
            pmove=pmove->next;
        }
        free(pmove);
    }
    

    创建一个新的临时结点去遍历整个链表进行打印

  • 数组实现

    void printStack(Stack s){
        int i;
        for(i=0;i<s->topofStack+1;i++){
            printf("%d ",s->Array[i]);
        }
        printf("\n");
    }
    

    数据在数组中直接打印就好,但要注意topofStack的初值为-1

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值