数据结构:栈(C语言实现)

隔了好几天才开始写,这几天在亲戚家里疲于奔命,话不多说,这次我们继续来学习栈。

栈给我个人的感觉就是一种倒过来的链表或者顺序表,我先选择用链表进行实现。

栈形象来说是一个杯子,每次你放进去一个元素,他都会先到杯子的底端,然后不断往上堆积;当你要取出元素的时候,你只能从最顶端开始拿,最后拿到最底端。

1.定义节点与栈

typedef struct NODE
{
    int data;//我这里以整型变量作为整个栈的元素类型
    struct NODE* next;//这是指向下一个节点的指针
}NODE,*LINK_NODE;

typedef struct stack
{
   LINK_NODE head;//这是整个站的头结点,也是栈顶,命名为top更好理解一些
   int size;//栈的大小
}stack;

2.进行初始化 

LINK_NODE initNODE(int element){
LINK_NODE newnode=(LINK_NODE)malloc(sizeof(NODE));
if (newnode == NULL) {  
        exit(EXIT_FAILURE);//处理申请内存失败的情况
    }  
newnode->data=element;//将节点中数据赋值为element
newnode->next=NULL;//先将指针定义为空
return newnode;
}
stack* initstack(){
    stack* newstack=(stack*)malloc(sizeof(stack));
     if (newstack == NULL) {  
        exit(EXIT_FAILURE);  
    }  
newstack->size=0;//初始时将栈的大小设置为0
newstack->head=NULL;//将栈顶的指针也设置为空
return newstack;
}

3.进行压栈(向其中填入元素) 与弹栈(从栈里面取出元素)

先来图理解一下

这是入栈,往上堆的过程

每一个节点我们都堆在上面 ,然后再把头节点(栈顶)进行修改,把新加入进来的元素的地址做为头结点(栈顶),进行更新。

void stackpush(stack*newstack,int element){
   LINK_NODE newnode=(LINK_NODE)malloc(sizeof(NODE));//申请一个新节点
   newnode->data=element;
   newnode->next=newstack->head;//将新节点与原来的栈顶连接起来
   newstack->head=newnode;//将栈顶更新为新节点的地址
   newstack->size++;//更新栈的长度
   }

出栈就更好理解了,就是上图的逆过程。先看代码

int stackpop(stack*newstack){
    if(newstack->size==0){
        printf("stackoverflow\n"); //如果栈的长度为零,就报错
        exit(1);
    }
   int returnelement;
   returnelement=newstack->head->data; /*这里我们要用一个新的变量来存储元素,
                                      因为在后面栈顶要被释放掉,就不能取用了*/
  LINK_NODE p2=newstack->head->next;  /*用一个新变量来存储栈顶的next指针,
                                       同样也是因为栈顶要被free掉*/
  free(newstack->head);  //释放栈顶
  newstack->head=p2;     //将栈顶更新为原来栈顶下面元素的地址,也就是栈顶的next指针
  newstack->size--;      //栈的大小减一
return returnelement;    //返回弹出的元素
}

出栈入栈的核心就是栈顶的更新问题,需要注意的就是栈顶在被释放过之后,栈顶中的int类型数据,next指针都是不能再被取用的了,因此我们需要另外用变量对这两个变量进行存储。

4.栈的销毁

这个按照顺序遍历节点free掉就好了。这里也是上面的那个问题,由于每次都要将栈顶释放,而对栈顶进行更新时,又要将原来栈顶的next指针变成现在的栈顶,因此还是要用新变量对next指针进行存储。

void stackdestory(stack* newstack){
    for(int i=0;i<newstack->size;i++){
        LINK_NODE p1=newstack->head->next;
        free(newstack->head);
        newstack->head=p1;
        newstack->size--;
    }

}

以上就是栈的基本操作了,这次用完整的源码给栈里压入5个元素并把他们弹出。

#include<stdio.h>
#include<stdlib.h>
typedef struct NODE
{
    int data;
    struct NODE* next;
}NODE,*LINK_NODE;

typedef struct stack
{
   LINK_NODE head;
   int size;
}stack;

LINK_NODE initNODE(int element){
LINK_NODE newnode=(LINK_NODE)malloc(sizeof(NODE));
if (newnode == NULL) {  
        exit(EXIT_FAILURE);  
    }  
newnode->data=element;
newnode->next=NULL;
return newnode;
}
stack* initstack(){
    stack* newstack=(stack*)malloc(sizeof(stack));
     if (newstack == NULL) {  
        exit(EXIT_FAILURE);  
    }  
newstack->size=0;
newstack->head=NULL;
return newstack;
}
void stackpush(stack*newstack,int element){
   LINK_NODE newnode=(LINK_NODE)malloc(sizeof(NODE));
   newnode->data=element;
   newnode->next=newstack->head;
   newstack->head=newnode;
   newstack->size++;
   }
int stackpop(stack*newstack){
    if(newstack->size==0){
        printf("stackoverflow\n");
        exit(1);
    }
   int returnelement;
   returnelement=newstack->head->data;
  LINK_NODE p2=newstack->head->next;
  free(newstack->head);
  newstack->head=p2;
  newstack->size--;
return returnelement;
}
void stackdestory(stack* newstack){
    for(int i=0;i<newstack->size;i++){
        LINK_NODE p1=newstack->head->next;
        free(newstack->head);
        newstack->head=p1;
        newstack->size--;
    }

}
int main(){
LINK_NODE node;
stack*stk;
stk=initstack();//初始化栈
for(int i=0;i<5;i++){
    stackpush(stk,i+2);//给栈中压入2,3,4,5,6
}
for(int j=0;j<5;j++){
    printf("%d\n",stackpop(stk));//将5个元素弹出
}

stackdestory(stk);//销毁栈
    return 0;
}

结果如下

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值