栈的总结

A summary of Stack and Code part

Posted by Zaki on December 27, 2019

之前一直只学习栈,有一次看到了“堆栈”这个词,后来才知道实际上栈(Stack)的全称就是“堆栈”。那为什么不叫堆,因为堆这个名字被另外一种叫heap的数据结构给用了,那莫得法子只好用栈喽。而就Stack来说,它的意思指的就是一件东西堆在另一个东西上的结构。今天刚好在这做一个关于栈(Stack)的小结。

引入

####引入代码

    include <stdio.h>
    include <malloc.h>
    void f(k)
    {
     int m;
     double *q=(double *)malloc(100);
    }
    int main()
    {
     int n;
     int *p=(int *)malloc(100);
     
     return 0;
    }

根据学过的知识,上面这段代码里面的变量m,n,p,q这些在等号左边并且是系统给你分配的,我们就说它在栈里分配。

而malloc后面的(100)则是在堆里分配的,这个是需要在座的程序猿手动分配的。

总的来说,凡是动态分配的在堆里分配,静态分配在栈里分配。成员变量在堆,局部变量在栈。

栈和堆表示分配数据的一种方式。静态的或局部变量它们这些是以压栈和出栈的方式分配内存的,动态的或成员变量它们是以堆排序的方式分配内存的。

定义

栈:一种可以实现“先进后出”的存储结构。

栈类似于一个上面开口底下封闭的箱子,你往里放书,先放进去的肯定最后才能拿出来,后放进去的肯定可以先拿出来。

分类

静态栈和动态栈(和链表那种类似)

算法

入栈和出栈

程序

####代码部分

  #include <stdio.h>
  #include <malloc.h>
  #include <stdlib.h>
  
  typedef struct Node{
   int data;
   struct Node*Next;
   }Node,*PNODE;//Node等价于struct Node,PNODE等价于struct Node *
   
   typedef struct Stack
   {
    PNODE pTop;
    PNODE pBottom;
   }STACK,*PSTACK;
   
   //PSATCK等价于struck Stack
   //pTop和pBottom都指向一个头指针,即为创建成功
   void init(PSTACK ps)//造出空栈 ps保存S的地址
   {
    ps->pTop=(PNODE)malloc(sizeof(NODE));//把头指针的地址给ptop,ptop此时指向头指针
    if {(NULL==ps->pTop)
    exit(-1);
    }
    else
    {
     ps->pBottom=ps->pTop;//把pTop的地址给到bottom,则两个都指向了头指针
     //ptop里存放了之前分配内存的地址,把这个地址赋给了pbottom,则pbottom也就指向了它
     ps->pTop->pNext=NULL;//清空指针域
    }
   }
   init函数完成了ptop和pbottom都指向了一个空栈
   void push(PSTACK ps,int val)
   {
    PNODE pNew=(PNODE)malloc(sizeof(NODE));//造一个新结点
    pNew->data=val;
    //下一步我们要让new结点指向下一个空栈,思路是把ptop的值赋给new,因为top里面存放的是空栈的地址
    pNew->pNext=ps->pTop;//虽然ptop和pbottom里都存放着前面空栈的地址
    //但只能选top,因为压栈是从头部往下压的,把top里存放的地址给new,那么new就指向了下一个空栈
    ps->pTop=pNew;//ptop指向了新的结点
   }
   
   void traverse(PSTACK ps)//遍历输出
   {
    PNODE p=ps->pTop;//p永远指向栈顶
    while (p!=ps->bottom)
    {
     printf("%d",p->data);
     p=p->pNext;
    }
    printf(" ");
   }
   
   bool empty(PSTACK ps)
   {
    if(ps->pTop==ps->pBottom)
    return ture;
    else
    return false;
   }
   
   //把ps所指向的栈出栈一次,并把出栈的元素存入pval形参所指向的变量中
   bool pop(PSTACK ps,int *pVal)
   {
    if (empt(PSTACK ps))//ps本身存放的就是S的地址
    {
    return false;
    }
    else
    {
    //这儿不能直接来一个pTop=pTop->pNext;内存没有释放
     PNODE r=ps->pTop;
     //旁边新加一个r,我们要让r指向栈顶,因为ptop本来是指向栈顶的
     //我们让r指向ptop所指的栈顶,即把ptop所指的指针赋给r,不就是r指向了栈顶嘛
     //把ptop指向的东西给r,r也就指向了这个东西
     *pVal=r->data;
     //赋值
     ps->pTop=r->pNext;
     //r的next指针也就是栈顶的右半边,右半边本来是指向栈顶下边的,
     //我们把r的next的指针(右半边)给ptop,那么ptop不就指向下边了
      free(r);
     r=NULL;//防止内存在后面使用r,释放
    }
    return true;
   }
   
   void clear(pSTACK ps)//清空元素
   if(empty(ps))
   {
    return;
    }
    else
    {
   PNODE p=ps->pTop;
   
   while(p!=ps->bottom)
    {
   ps->pTop=p->pNext;
    free(p);
    }
   }
   
   int main(void)
   {
   STACK S;
   init(&S);
   push(&S,1);
   push(&S,2);
   pop(&S,&val);
   printf("%d",val);
   traverse(&S);
   clear(&S);
   }

应用

1.函数调用 2.中断 3.表达式 4.中断求值 5.内存分配 6.缓冲处理 7.迷宫