数据结构基础(4)C语言实现栈--链式存储(动态栈)

写程序的时候,我们经常会说基本类型变量存在栈内存,引用类型的变量(对象,数组)存在堆内存。现在我们来看看栈这种数据结构是怎么实现的。

定义

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

栈类似于往箱子放衣服,先放的最后拿

栈的分类:

静态栈:以数组方式实现,删除时删除下标最大的,插入时从最大下标+1插入

动态栈:以链表方式实现,删除和插入都是从头部

算法:出栈(POP),入栈(PUSH)

应用:

1.      函数调用 :在函数f中调用另一个g函数,在g函数中调用k函数

执行到要调用g函数位置,先把g函数执行后下一句的地址以及变量压栈,执行g函数,执行到调用k函数的位置,再把k函数执行后的下一句压栈,然后执行k函数,执行后取出栈顶元素,赋给CPU,执行g函数中调用k函数后的下一句。

2.中断

3.表达式求值:3*2+5/6-4两个栈实现,一个放运算符,一个放数据

4.内存分配:把函数形参压入栈中

5.缓冲处理

6.走迷宫

C语言实现:

下面是C语言实现动态栈的代码,为了方便在栈底部建立一个头结点,不存有效数据。先看图:

#include<stdio.h>
#include<malloc.h>
#include<stdbool.h>
//栈有一个不存放有效数据的头节点,Pbotom始终指向头结点。
/**
**定义节点的结构体
*/
 typedef struct Node{
   int data;//数据域
   struct Node * PNext;//指针域
} Node,*PNext;
/**
**定义栈的结构体
*/
typedef struct Stack {
 PNext top;
PNext bottom;
}Stack,* PStack;
/**
**初始化栈
*/
void  init(PStack PStack )
{
    //建立一个不存任何有限元素的头结点,作为栈底
   PStack->bottom=malloc(sizeof(Node));
   PStack->top=PStack->bottom;
   PStack->top->PNext=NULL;
}
/**
*遍历栈
**/
void traverse(PStack Ps )
{
    if(Ps->bottom==Ps->top)
    {
        printf("栈为空\n");
        return ;
    }
    PNext pt=Ps->top;
    while(pt!=Ps->bottom)//不能把pt换成ps->top这样就修改了链表。尴尬。。
    {
       printf("%d ",pt->data);
       pt=pt ->PNext;
    }
    printf("\n");
    return ;

}
/**
**入栈
*/
void push(PStack Pstack,int val)
{
   PNext Pnew=malloc(sizeof(Node));//生成一个新节点
   Pnew->data=val;
   Pnew->PNext=Pstack->top;
   Pstack->top=Pnew;
}
/**
**出栈
*/
void pop(PStack ps )
{
  if(ps->top==ps->bottom)
  {
      printf("栈为空,无法完成出栈操作\n");
      return;
  }
  PNext temp=ps->top;//引入辅助变量,用于释放内存
  ps->top=ps->top->PNext;
  free(temp);
  temp=NULL;
}
/**
**清空栈
*/
void clear(PStack ps)
{
    while(ps->top!=ps->bottom)
    {
        PNext temp=ps->top;
        ps->top=ps->top->PNext;
        free(temp);
    }
}
int main()
{
Stack stack;
init(&stack);
push(&stack,6);
push(&stack,7);
push(&stack,8);
traverse(&stack);
 pop(&stack);
traverse(&stack);
clear(&stack);
traverse(&stack);
push(&stack,7);
traverse(&stack);
return 0;
}
时间: 2024-08-29 05:00:44

数据结构基础(4)C语言实现栈--链式存储(动态栈)的相关文章

数据结构_线性表_顺序存储之1顺序栈2共享栈_链式存储之链栈_栈的应用举例

1>//栈是先进后出,后进先出的线性表 简称LIFO线性表 //栈的顺序存储结构成为顺序栈(sequebtial stack). //顺序栈利用一组地址连的存储单元依次存放从栈底到 栈顶的数据元素,通常用一维数组存放栈的元素 //"指针"top并非指针,而是表示栈顶元素的当前位置 //top不是指针型变量而是整形变量,top=0空栈,top=MaxSize 表示满栈,当top>maxsize 表示栈溢出 代码 #include <stdio.h> #includ

栈及栈的链式存储结构(栈链)

栈:线性结构,后进先出.栈(Stack)是一种特殊的线性表(顺序表,链表)只在表尾进行删除和插入操作. 注意:对于栈来说,表尾称为栈的栈顶(top),表头称为栈底(bottom). 栈也是线性结构的一种特例.与队列不同,他只有一个口,只能从这里读或者写数据,这个口称为栈顶(top).栈是一种先进后出的数据结构.先进来的元素会放入栈底,而后进来的元素被放在它的上面,最后进来的元素的上面的位置,称为栈顶. 栈所提供的操作比一般的线性表要少很多,只提供:初始化.销毁.判断是否为空.求栈的长度.清空栈.

数据结构第六篇——顺序存储结构与链式存储结构的特点

?注:未经博主同意,不得转载. 两者特点: 顺序表的特点是逻辑上相邻的数据元素,物理存储位置也相邻,并且,顺序表的存储空间需要预先分配. 它的优点: (1)方法简单,各种高级语言中都有数组,容易实现. (2)不用为表示节点间的逻辑关系而增加额外的存储开销. (3)顺序表具有按元素序号随机访问的特点. 缺点: (1)在顺序表中做插入.删除操作时,平均移动表中的一半元素,因此对n较大的顺序表效率低. (2)需要预先分配足够大的存储空间,估计过大,可能会导致顺序表后部大量闲置:预先分配过小,又会造成溢

数据结构开发(5):线性表的链式存储结构

0.目录 1.线性表的链式存储结构 2.单链表的具体实现 3.顺序表和单链表的对比分析 4.小结 1.线性表的链式存储结构 顺序存储结构线性表的最大问题是: 插入和删除需要移动大量的元素!如何解决? 链式存储的定义: 为了表示每个数据元素与其直接后继元素之间的逻辑关系:数据元素除了存储本身的信息外,还需要存储其直接后继的信息. 链式存储逻辑结构: 基于链式存储结构的线性表中,每个结点都包含数据域和指针域 数据域:存储数据元素本身 指针域:存储相邻结点的地址 专业术语的统一: 顺序表 基于顺序存储

数据结构第五篇——线性表的链式存储之循环链表

?注:未经博主同意,不得转载. 链表是另一种形式的链式存储结构,它是线性链表的一种变形.在线性链表中,每个结点的指针都指向它的下一个结点,最后一个结点的指针域为空,表示链表的结束.若使最后一个结点的指针指向头结点,则链表呈环状,这样的链表称为循环链表. 循环链表当然也分为单链表和双向列表. 通常情况下,在循环链表中设立尾指针而不设头指针,可使某些操作简化. 循环链表的定义和操作与单链表类似,只是循环结束条件有所不同,下面只给出单循环链表的定义和部分操作,至于双向循环链表可能会在以后的项目中出现,

数据结构第三篇——线性表的链式存储之单链表

线性表的链式存储结构的特点是用一组任意的存储单元来存储线性表的数据元素,这些单元可以分散在内存中的任意位置上,其在物理上可以是连续的,也可以是不连续的.具有链式存储结构的线性表称为线性链表. 为了表示出每个数据元素与其后继之间的关系,除了存储数据元素本身的信息之外,还需存储指示其直接后继的信息.这可以用一个结点(node)来完整的表示. 将节点中存储数据元素本身信息的域称为数据域:存储其直接后继位置的域称为指针域.指针域中存储的信息称作指针或链. 一般情况下,链表中每个结点可以包含若干个数据域和

数据结构之栈——链式存储结构(php代码实现)

<?php /**     1. DestroyStack(): 栈的销毁     2. ClearStack(): 将栈置为空栈     3. StackEmpty(): 判断栈是否为空     4. StackLength(): 返回栈的长度     5. GetTop(): 取得栈顶的元素     6. Push(): 插入新的栈顶元素     7. Pop(): 删除栈顶元素     8. StackTraverse(): 遍历栈元素  */ class LNode{     publi

数据结构第四篇——线性表的链式存储之双向链表

?注:未经博主同意,不得转载. 前面讨论的单链表,每个结点中只有一个指针域,用来存放指向后继结点的指针,因此,从某个结点出发只能顺时针往后查找其他结点.若要查找某个结点的直接前驱,则需要从头指针开始沿链表探寻,处理起来十分不方便.为克服单链表的这一缺点,可引入双向链表. 双向链表中每一个结点含有两个指针域,一个指针指向其直接前驱结点,另一个指针指向直接后继结点.和单链表类似,双向链表一般也只有头指针唯一确定:同样也可设头结点,使得双向链表的某些操作简便一些. 双向链表结构定义如下:  双向链表是

C 栈 链式存储

#ifndef _MY_LINKSTACK_H_ #define _MY_LINKSTACK_H_ typedef void LinkStack; LinkStack* LinkStack_Create(); void LinkStack_Destroy(LinkStack* stack); void LinkStack_Clear(LinkStack* stack); int LinkStack_Push(LinkStack* stack, void* item); void* LinkSta