从小白开始自学数据结构——第四、五天【栈及其基本操作】

电脑死机了、、、昨天的笔记凉了,今天重新梳理了一次。
数据结构
狭义:
数据结构是专门研究数据存储的问题
数据的存储包含两个方面:个体存储 + 个体关系存储

广义:
      数据结构既包含了数据的存储,也包含了对数据的操作
      对存储数据的操作即为算法

算法
狭义:
算法是和数据存储方式密切相关
广义:
算法和数据的存储方式无关
这就是泛型的思想

数据存储结构有几种
线性
连续存储【数组】
优点
存取速度很快
空间有限制
缺点
插入删除元素很慢(要移动其他元素)
事先必须知道数组的长度
空间有限,需要一大块连续内存

    离散存储【链表】
        优点
            空间没有限制
            插入删除元素速度很快
            存储容量无限制
        缺点
            存取的速度很慢,需要遍历

    线性结构的应用--栈
        定义
            一种可以实现“先进后出”的存储结构
            类似于一个箱子
            本质就是一个操作受限制的链表

        分类
            静态栈
            动态栈
        基本操作
            创建空栈
            空判断
            压栈
            遍历输出
            出栈
            清空

        应用
            函数调用
            中断
            表达式求值
            内存分配
            缓冲处理
            迷宫

基本操作实现:

/*******************************

        栈及其基本操作

*******************************/

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

struct LinkList
{
    int date;
    struct LinkList * next;
};

struct Stack
{
    struct LinkList * pBottom;
    struct LinkList * pTop;
}; 

void creat_stack (struct Stack *);            //创建空栈
bool is_empty (struct Stack *);              //空判断
void push_stack (struct Stack * ,int );     //压栈
void traverse_stack (struct Stack *);      //遍历输出
bool pop_stack (struct Stack * ,int *);   //这个有返回值是因为出栈可能失败,即栈为空的时候
void clear_stack (struct Stack *);       //清空

int main ()
{
    int val;
    struct Stack S;
    creat_stack (&S);
    push_stack(&S, 99999);
    push_stack(&S, 1);
    push_stack(&S, 3);
    push_stack(&S, 1);
    push_stack(&S, -56);

    traverse_stack(&S);//输出是倒过来的,因为第一个元素被压到最下面了,从上面出栈,就是倒过来的

    pop_stack(&S, &val);
    traverse_stack(&S);
    printf ("出栈的元素是%d\n", val);

    clear_stack (&S);
    pop_stack(&S, &val);
    traverse_stack(&S);

    return 0;
}

void creat_stack (struct Stack * p)
{
    /*创建空链表
    判断链表创建是否成功
    头结点数据域为空
    底指向头结点
    头指向头结点*/
    struct LinkList * pHead = (struct LinkList *)malloc(sizeof(struct LinkList));
    if (!pHead)
    {
        printf ("创建失败\n");
        exit(1);
    }
    pHead->date = NULL;
    pHead->next = NULL;

    p->pTop = pHead;
    p->pBottom = pHead;

    return;
}

bool is_empty (struct Stack * p)
{
    if (p->pTop == p->pBottom )
    {
        return true;
    }
    else
        return false;
}

void push_stack (struct Stack * p, int val)
{
    /*创建一个新的结点
    判断新结点是否创建成功
    新结点指向原来结点
    将pTop指向新结点*/
    struct LinkList * pNew = (struct LinkList *)malloc(sizeof(struct LinkList));
    if (!pNew)
    {
        printf ("创建失败\n");
        exit(1);
    }
    pNew->date = val;
    pNew->next = NULL;

    pNew->next=p->pTop;  //p->pTop ->next = pNew;是把原来那个结点当做了尾,然后新建一个指向尾
    p->pTop = pNew;

    return;
}

void traverse_stack (struct Stack * p)
{
    if ( is_empty(p) ==true )
    {
        printf ("空栈\n");
        return;
    }
    int i=0;
    struct LinkList * q;
    q = p->pTop;
    while (q->next)
    {
        i++;
        printf ("栈中第%d个元素为:%d \n", i,q->date);
        q = q->next;
    }
    return;
}

bool pop_stack (struct Stack * p,int * val)
{
    /*判断栈是否为空
      不为空则把栈顶的值返回给val
      释放其空间
      返回true
    */
    struct LinkList * q=p->pTop ;     //struct Stack * q;
    if ( is_empty(p) == true)
    {
        printf ("空栈\n");
        return false;
    }
    *val = q->date;                   // *val = p->pTop->date;
                                      //q = p;
    p->pTop = q->next;                //p->pTop = p->pTop ->next ;
    free (q);                         //free(q->pTop);        注释的这一块是错误的,因为p->pTop是一个结点,struct Stack * q是一个栈
    return true;
}
//感觉这个就是彻头彻尾的一个不能插入不能删除中间的链表,栈顶就是头指针指向首结点,栈底就是一个指向尾结点的指针

void clear_stack (struct Stack * p)
{
    struct LinkList * r;
    struct LinkList * q=p->pTop;    
    if ( is_empty(p) == 1)
    {
        printf ("本来就是空的\n");
        return;
    }
    else
        while (q != p->pBottom )
        {
            r = q->next;
            free (q);
            q=r;
        }

    p->pTop =p->pBottom ;
    return;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值