数据结构学习(三)、栈

栈是一种特殊的线性表。大家可能会有疑问,竟然栈是一种线性表,那为什么还要定义栈呢?因为栈的引入简化了程序设计的问题,

使我们思考范围更小,只需关注top位置。线性表分为顺序存储和链式存储,栈是线性表,所以也有这两种存储方式。同样,

栈作为一种特殊的线性表,也同样存在这两种存储方式。我们先来看栈的顺序存储结构。

顺序栈结构体如下:

#define MAXSIZE /*存储空间初始分配量*/
typedef int ElemType;/*存放的数据类型*/
typedef struct
{
   ElemType data[MAXSIZE];
   int top;
} SqStack;

现在有一个栈,MAXSIZE为5,则栈普通情况,空栈,满栈的情况如下图所示

顺序栈初始化操作

顺序栈初始化操作实际就是将top指向-1操作

Status InitStack(SqStack *S)
{
    S->top = -1;
    return OK;
}

顺序栈入栈操作

入栈操作实际就是将top增加一,讲新元素赋值给栈顶空间

Status Push(SqStack *S,ElemType e)
{
    if(S->top == MAXSIZE-1)
        return ERROR;
    S->top++;
    S->data[S->top] = e;
    return OK;
}

顺序栈出栈操作

出栈的操作实际就是将栈顶元素辅助给e,栈顶指针减一

Status Pop(SqStack *S,ElemType *e)
{
    if(S->top == NULL)
        return ERROR;
    *e = S->data[S->top];
    S->top--;
    return OK;
}

顺序栈(两栈共享空间)

思路:两栈别人处于数组二端,向中间靠拢。可以想象,只要他们指针不相遇,二个栈就能一直使用。

其结构体如下:

#define MAXSIZE 10
typedef struct
{
    ElemType data[MAXSIZE];
    int top1;
    int top2;
}DuStack;

两栈初始化操作

两栈初始化操作实际就是将top1指向-1,top2指向MAXSIZE操作

Status InitStack(DuStack *S)
{
    S->top1 =-1;
    S->top2 =MAXSIZE;
    return OK;
}

两栈入栈操作

对于双栈的入栈操作,我们除了要插入元素值外,还需要判断是栈1还是栈2的栈号参数。

/**
    入栈操作
    @params S 共享空间指针变量
    @params e 入栈数据
    @params stackNumber 栈号 1为一号栈 2为二号栈
*/
Status Push(DuStack *S,ElemType e,int stackNumber)
{
    if(S->top1+1 == S->top2)
        return ERROR;
    if(stackNumber == 1)
    {
        S->top1++;
        S->data[S->top1] = e;
    }else if(stackNumber==2){
        S->top2--;
        S->data[S->top2] = e;
    }
    return OK;
}

两栈出栈操作

对于双栈的入栈操作,我们除了要一个接收出栈的值,同样还需要判断是栈1还是栈2的栈号参数。

/**
    出栈操作
    @params S 共享空间指针变量
    @params e 出栈数据存放指针变量
    @params stackNumber 栈号 1为一号栈 2为二号栈
*/
Status Pop(DuStack *S,ElemType *e,int stackNumber)
{
    if(stackNumber == 1){
        if(S->top1 == NULL)
            return ERROR;
        *e = S->data[S->top1];
        S->top1--;
    }
    if(stackNumber == 2){
        if(S->top2 == MAXSIZE)
            return ERROR;
        *e = S->data[S->top2];
        S->top2++;
    }
    return OK;
}

双栈应用

适合二个栈空间需求有相反关系时。

链栈

链栈结构体如下:

typedef struct Node
{
    ElemType data;
    struct Node * next;
}Node,*LinkStackPtr;

typedef struct LinkStack
{
    int count;
    LinkStackPtr top;
}LinkStack;

链栈初始化

初始化操作实际就是将top指针指空,链表计数为零。

/*
    初始化共享空间栈,无头结点
    @params LinkStack S 栈指针变量
*/
Status InitStack(LinkStack * S)
{
/*    S->top = (LinkStackPtr *)malloc(sizeof(Node));
    if(!S->top)
        return ERROR;*/
    S->count = 0;
    S->top=NULL;
    return OK;
}

链栈进栈操作

进栈操作先分配一个结点,并为结点赋值,把当前栈顶元素赋值给新结点的直接后继,将新的结点赋值给栈顶指针,链表计数加一。

/*
    入栈操作
    @params LinkStack S  栈指针变量
    @params ElemType e  入栈值
*/
Status Push(LinkStack * S,ElemType e)
{
    LinkStackPtr r;
    r = (LinkStackPtr)malloc(sizeof(Node));
    if(!r)
        return ERROR;
    r->data =e;
    r->next = S->top;
    S->top = r;
    S->count ++;
    return OK;
}

链栈出栈操作

出栈操作需先判断是否为空栈,若否,则将栈顶结点值赋给e,将栈顶结点赋值给p,使栈顶指针指向后一个结点,释放p,链表计数减一。

/*
    出栈操作
    @params LinkStack S  栈指针变量
    @params ElemType *e  出栈保存地址
*/
Status Pop(LinkStack * S,ElemType *e)
{
    LinkStackPtr p;
    if(S->top==NULL)
        return ERROR;
    p  = S->top;
    *e = p->data;
    S->top = p->next;
    S->count --;
    free(p);
    return OK;
}
时间: 2024-10-31 05:02:08

数据结构学习(三)、栈的相关文章

数据结构学习总结 栈和队列

一,顺序栈的基本操作 同顺序表和链表一样,栈也是用来存储逻辑关系为 "一对一" 数据的线性存储结构,如图 1 所示.                                                               图 1 栈存储结构示意图 从图 1 我们看到,栈存储结构与之前所学的线性存储结构有所差异,这缘于栈对数据 "存" 和 "取" 的过程有特殊的要求: 1,栈只能从表的一端存取数据,另一端是封闭的,如图 1 所示

数据结构学习之栈

本例主要是实现一个顺序栈:其它的啥也不说:直接上代码: /*或许这就是指针的魅力:也是指针折磨人的地方.指针可以直接对内存进行操作,非常强大:它操作的对象是地址:是计算机最本质的东西:你在操作的时候是比较爽了:但是当你在程序中“不小心”改变了指针变量的值:当你再次访问时:就会出现一些莫名其妙的错误(通常是访问了不该访问的内存,因为指针的内容变了:但是程序的逻辑是没有任何错误的:你就会变得特别崩溃:本例具体的错误如下所示): */ #include<stdio.h>#include<std

数据结构学习--Java栈和队列

栈:先进后出 队列:先进先出 都是数组存放,但是删除的时候不是删除了数组中的数据,而是使用增加游标标识的方式实现删除,“游标标识”加加或者减减完成删除操作,查看的时候,也不是直接查看栈和队列的数组元素,而是使用游标的方式向外查看. 栈的实现 package com.example.deer; public class MyStack { private long[] arr; private int top; /** * 默认构造函数 */ public MyStack(){ arr = new

一步一步学习数据结构(三)栈的顺序存储结构实现代码

//栈这种逻辑结构的实现与一般线性表的实现类似,有两种存储方式:顺序存储和链式存储 //先学习顺序存储 //1. #include<stdio.h> #include<stdlib.h> #define null NULL #define SIZE 100 typedef int dataType ; typedef struct { dataType data[SIZE]; int top; }cStack,*cStackPointer; //初始化栈空间 void initSt

数据结构实验三《栈和队列》

<数据结构>实验三 栈和队列 一.实验目的 巩固栈和队列数据结构,学会运用栈和队列. 1.回顾栈和队列的逻辑结构和受限操作特点,栈和队列的物理存储结构和常见操作. 2.学习运用栈和队列的知识来解决实际问题. 3.进一步巩固程序调试方法. 4.进一步巩固模板程序设计. 二.实验时间 准备时间为第5周到第6周,具体集中实验时间为6周第2次课.2个学时. 三.实验内容 1.自己选择顺序或链式存储结构,定义一个空栈类,并定义入栈.出栈.取栈元素基本操作.然后在主程序中对给定的N个数据进行验证,输出各个

数据结构实验之栈三:后缀式求值

数据结构实验之栈三:后缀式求值 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 对于一个基于二元运算符的后缀表示式(基本操作数都是一位正整数),求其代表的算术表达式的值. 输入 输入一个算术表达式的后缀式字符串,以'#'作为结束标志. 输出 求该后缀式所对应的算术表达式的值,并输出之. 示例输入 59*684/-3*+# 示例输出 57 提示 基本操作数都是一位正整数! 来源 示例程序 #include <stdio.h>

数据结构学习笔记之栈

栈(stack)  是限定仅在表尾进行插入或删除操作的线性表.因此,对栈来说,表尾端有其特殊含义,称为栈项(top),相应地,表头端称为栈底(bottom).不含元素的空表称为空栈. 栈有两种存储表示方法:顺序栈和链栈.顺序栈,即栈的顺序存储结构是利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针top指示栈顶元素在顺序栈中的位置.通常的习惯做法是以top=0表示空栈,鉴于C语言中数组的下标约定从0开始,则当以C作描述语言时,如此设定会带来很大不便:另一方面,由于栈在使用过程

数据结构实验之栈三:后缀式求值 (stack)

数据结构实验之栈三:后缀式求值 Time Limit: 1000MS Memory limit: 65536K 题目描述 对于一个基于二元运算符的后缀表示式(基本操作数都是一位正整数),求其代表的算术表达式的值. 输入 输入一个算术表达式的后缀式字符串,以‘#’作为结束标志. 输出 求该后缀式所对应的算术表达式的值,并输出之. 示例输入 59*684/-3*+# 示例输出 57 1 #include<stdio.h> 2 #include<string.h> 3 #include&

小猪的数据结构学习笔记(三)

小猪的数据结构学习笔记(三) 线性表之单链表 本章引言: 上一节中我们见识了第一个数据结构--线性表中的顺序表; 当你把操作的代码自己写几遍就会有点感觉了,如果现在让你写顺序表的 插入算法,你能够想出大概的代码么?如果可以,那么你就可以进入新的章节了; 否则,还是回头看看吧!在本节,我们将迎来线性表的链式表示--单链表 单链表和顺序表有什么优势和劣势呢?单链表的头插法和尾插法有什么不同呢? 请大家跟随笔者的脚步来解析线性表中的单链表把! 本节学习路线图 路线图解析: ①先要理解顺序表和单链表各自