数据结构-3.4-栈与队列

学习资料:数据结构C语言版 清华大学出版社(以后的略)

这次一次过把栈和队列都写好了。栈和队列 存储结构和顺序表有些像。不过栈是先进后出,队列是先进先出。

栈和队列的应用其实还是挺多的,不过我属于入门学习阶段……所以就先把最基本的代码给实现了……学完整本课内要求的数据结构内容后会将这些各种各样的数据结构应用在别的题目上的!!!

栈:时限定仅在表尾进行插入或者删除操作的线性表。表尾成为栈顶,表头段称为栈底。不含元素的栈称为空栈。

栈的实现:

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<iostream>
  4 using namespace std;
  5 #define TRUE 1
  6 #define FALSE 0
  7 #define OK 1
  8 #define ERROR 0
  9 #define OVERFLOW -2
 10 #define STACK_INIT_SIZE 100//存储空间的初始分配量
 11 #define STACKINCREMENT 10//存储空间分配增量
 12
 13 typedef int Status;
 14 typedef int Selemtype;
 15 typedef struct node
 16 {
 17     int data;
 18     struct node *next;
 19 } Stack;
 20
 21
 22 Status IsEmpty(Stack *t)
 23 {
 24     if(t->next==NULL)
 25     {
 26         return TRUE;
 27     }
 28     return FALSE;
 29 }
 30 void InitStack(Stack *top)
 31 {
 32     top->next=NULL;//将栈顶设为空
 33 }
 34 Status Push(Stack *top,Selemtype e)
 35 {
 36     //创造新的节点 存放传入的e
 37     Stack *p;
 38     p=(Stack*)malloc(sizeof(Stack));
 39     if(p==NULL)
 40     {
 41         return 0;
 42     }
 43     p->data=e;
 44     p->next=top->next;
 45     top->next=p;
 46     return OK;
 47 }
 48 Status Pop(Stack *top,Selemtype &e)
 49 {
 50     if(IsEmpty(top)) return 0;
 51     Stack *p;
 52     p=top->next;//栈顶下面第一个节点是要出栈的
 53     e=p->data;
 54     top->next=p->next;//栈内元素的前移
 55     free(p);
 56     return OK;
 57 }
 58
 59
 60 int main()
 61 {
 62     int a;
 63     Stack *top=(Stack*)malloc(sizeof(Stack));//生成一个栈顶指针
 64     InitStack(top);
 65     while(~scanf("%d",&a))
 66     {
 67         Push(top,a);
 68     }
 69     Stack *p=top->next;
 70     printf("the elemet in the stack:\n");
 71     while(p)
 72     {
 73         printf("%d ",p->data);
 74         p=p->next;
 75     }
 76     cout<<endl;
 77
 78     int x;
 79     Pop(top,x);
 80     cout<<"The ele that you delete is "<<x<<" ."<<endl;
 81
 82     p=top->next;
 83     printf("the elemet in the stack:\n");
 84     while(p)
 85     {
 86         printf("%d ",p->data);
 87         p=p->next;
 88     }
 89     p=NULL;
 90
 91     cout<<endl;
 92     cout<<"Now pop all the data:"<<endl;
 93     while(Pop(top,x))
 94     {
 95         printf("%d ",x);
 96     }
 97     cout<<endl;
 98     free(top);
 99     return 0;
100 }

功能函数:

1、IsEmpty:判断栈是否为空,传入指向头结点的指针,判断栈顶项是否为空。若为空返回true,否则返回false。

2、InitStack:使传入的头结点指针一个指为空。

3、Push:创造一个新的结点(分配相应的存储空间),在该生成的结点的数据域里面存放传入的Selemtype e。该生成的结点放在栈顶位置,原栈顶元素及以下均往后推一个位置。(实现的时候只是改变了指针的指向,像单链表)。

4、Pop:需要判断栈是否为空。生成一个指向栈的指针指向栈顶元素,释放栈顶元素的空间,原指向栈顶的头指针指向栈顶指向的next地址。会将出栈数据赋值到传入的Selemtype e上。方便输出检查结果。

5、主函数:对上述几个函数进行了相应的测试。先为栈顶分配sizeof(Stack)的内存空间,调用InitStack函数将栈置空。将栈置空后调用Push函数,以ctrl+z结束输入。输入一定的数据,将数据按顺序压入栈内,再调将压入栈内的元素按照从栈顶到栈尾的顺序输出(其实我觉得我可以将这一段再写一个小函数,使代码功能划分更强……)。调用Pop函数删除栈顶元素后再遍历输出一次栈内元素。最后顺序调用Pop函数将所有剩余的存储的数据出栈。

{写到这里我想到了一个问题,为什么每一次分配内存空间的时候都要将分配的内存空间置空(或者清0)呢?

询问了老师和百度了一下才知道原来(不要打我,我真的今天才知道这么一回事……以前都是按照书本代码养成的习惯……)在分配新的内存空间的时候这个空间里原本是存放着一些数据的。按理来说,是可以直接使用这段内存,可是万一存放的时候存在没有存放新数据但是却分配了内存的空间段,在检查结果输出数据的时候很可能会把原来存放在这个内存空间里的数据输出来,可能会造成难以发现的错误。}

队列:是一种先进先出的线性表结构。只允许在表的一端插入,在另一端删除元素。类似我们日常生活中的排队。允许插入的一端称为队尾,删除的一端称为队头。这里用了链队列的链式表示实现的代码。

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<iostream>
  4 using namespace std;
  5 #define TRUE 1
  6 #define FALSE 0
  7 #define OK 1
  8 #define ERROR 0
  9 #define OVERFLOW -2
 10
 11 typedef int Status;
 12 typedef int ElemType;
 13
 14 //定义队列
 15 typedef struct node{
 16     int data;
 17     struct node *next;
 18 }Queue;
 19 //定义队首队尾
 20 typedef struct pointer{
 21     Queue *front;//队首指针,不存放队列元素(类似链表中的表头
 22     Queue *rear;//队尾指针,存放队尾的数据元素
 23 }Qpointer;
 24
 25 //队列的初始化
 26 void QueueInit(Qpointer *qp)
 27 {
 28     Queue *que;
 29     que=(Queue*)malloc(sizeof(Queue));
 30     que->next=NULL;//队首和队尾指向同一个内存空间,指针域为NULL
 31     qp->front=que;
 32     qp->rear=que;
 33 }
 34
 35 int IsEmpty(Qpointer *qp)
 36 {
 37     if(qp->front==qp->rear)
 38     {
 39         return TRUE;
 40     }
 41     return FALSE;
 42 }
 43
 44 int QueuePush(Qpointer *qp,int e)
 45 {
 46     Queue *que;
 47     que=(Queue*)malloc(sizeof(Queue));//为新生成的结点分配内存空间
 48     if(que==NULL)
 49     {
 50         return 0;
 51     }
 52     que->data=e;
 53     que->next=NULL;
 54     qp->rear->next=que;//将节点插入队列尾
 55     qp->rear=que;
 56     return 0;
 57 }
 58 int QueuePop(Qpointer *qp,int *e)
 59 {
 60     Queue *que;
 61     if(IsEmpty(qp))
 62     {
 63         return 0;
 64     }
 65     que=qp->front->next;//que指向队列头结点的下一个节点,即真正的队首
 66     *e=que->data;//将要出队列的元素
 67     qp->front->next=que->next;
 68     //判断队列是否就只剩下一个元素
 69     if(qp->rear==que)
 70     {
 71         qp->rear=qp->front;
 72     }
 73     free(que);
 74     return OK;
 75 }
 76
 77 int main()
 78 {
 79     Qpointer *qp;
 80     int x;//队列的初始化
 81     qp=(Qpointer*)malloc(sizeof(Qpointer));
 82     QueueInit(qp);
 83
 84     scanf("%d",&x);//以零结束
 85     while(x!=0)
 86     {
 87         QueuePush(qp,x);
 88         scanf("%d",&x);
 89     }
 90     cout<<"Now output the queue. "<<endl;
 91     Queue *p=qp->front->next;
 92     if(p==NULL)    return 0;
 93     while(p)
 94     {
 95         printf("%d ",p->data);
 96         p=p->next;
 97     }
 98     printf("\n");
 99     //队列的删除
100
101     printf("delete the first data of queue:\n");
102     QueuePop(qp,&x);
103     p=qp->front->next;
104     if(p==NULL)
105     return 0;
106     while(p)
107     {
108         printf("%d ",p->data);
109         p=p->next;
110     }
111     cout<<endl;
112     //队列的最后删除
113     printf("delete queue:\n");
114     while(QueuePop(qp,&x))
115     {
116         printf("%d ",x);
117     }
118     printf("\n");
119     p=qp->front;
120     free(p);
121     free(qp);
122     return 0;
123
124 }

队列的定义:使用了两个结构体去定义队列。node结构体定义了一个数据域和一个指针域。pointer定义了队首指针和队尾指针,其中队首指针指向的node数据域为空,队尾指针指向的node存放队尾的数据元素。

1、QueueInit:队列的初始化。在主函数中会生成一个指向Queue的指针。传入这个指针,为其分配sizeof(Queue)的内存空间。并使队首和队尾指向同一个内存空间。

2、IsEmpty:判断队列是否为空。判断方法:队首指针和队尾指针是否相同。是返回true,否则返回false。

3、QueuePush:为新生成的结点分配内存空间,需要判断队列是否为空。(为啥呢……)将传入的e值赋给新生成结点的数据域。将新生成结点插入到队尾。

4、QueuePop:需要判断队列是否为空。将要出队的元素赋值给传入的地址e方便输入检查结果。需要最后判断一下队列是否只剩下了一个元素,如果是的话就要将队列的队首赋值给队尾(好销毁)。最后释放que指针。

5、主函数:队列的初始化,先生成一个指向Qpointer的指针,为其分配内存空间。调用QueueInit函数初始化。输入数据以0结束(原本想用~scanf来写,可是不知道为什么不好使了……改了就出错……)调用QueuePush函数再次将输入的数据入队。顺序输出输入的函数(其实我觉得可以写一个void的函数来实现这个过程……)。调用QueuePop函数,将队首元素出队,再遍历输入队里的数据。最后像栈一样多次调用QueuePop函数将所有队员出队,最后销毁指针,释放内存空间。

实现了基础的栈和队列……比较开心。

时间: 2024-08-07 00:15:31

数据结构-3.4-栈与队列的相关文章

数据结构与算法--栈、队列(队列)

Hello,everybody.我们又见面了.今天我们来学习一下队列这个数据结构,let's Go,开始我们的征程吧. 首先,举两个生活中的常见例子.相信大家,在用电脑工作娱乐时,都会碰到这样的现象.当我们点击程序或进行其他操作时,电脑处于死机状态.正当我们准备Reset时,它突然像打了鸡血似的,突然把刚才我们的操作,按顺序执行了一遍.之所以会出现这个现象,是因为操作系统的多个程序,需要通过一个管道输出,而按先后顺序排队造成的. 还有有个例子,在我们打客服热线时,有时会出现等待的现象.当其他客户

4、蛤蟆的数据结构笔记之四栈和队列定义

4.蛤蟆的数据结构笔记之四栈和队列定义 本篇名言:"人生应该如蜡烛一样,从顶燃到底,一直都是光明的." 今天学习栈和队列了.从第二篇学习时候我们知道,其实也是线性表的一种. 我们先来看下定义. 欢迎转载,转载请标明出处: 1.  栈 栈(stack)又名堆栈,它是一种运算受限的线性表.其限制是仅允许在表的一端进行插入和删除运算.这一端被称为栈顶,相对地,把另一端称为栈底.向一个栈插入新元素又称作进栈.入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素:从一个栈删除元素又称

SDUT 2449 数据结构实验之栈与队列十:走迷宫

数据结构实验之栈与队列十:走迷宫 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 一个由n * m 个格子组成的迷宫,起点是(1, 1), 终点是(n, m),每次可以向上下左右四个方向任意走一步,并且有些格子是不能走动,求从起点到终点经过每个格子至多一次的走法数. Input 第一行一个整数T 表示有T 组测试数据.(T <= 110) 对于每组测试数据: 第一行两个整数n, m,表示迷宫有n * m 个格子.(1

SDUT-3335_数据结构实验之栈与队列八:栈的基本操作

数据结构实验之栈与队列八:栈的基本操作 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 堆栈是一种基本的数据结构.堆栈具有两种基本操作方式,push 和 pop.push一个值会将其压入栈顶,而 pop 则会将栈顶的值弹出.现在我们就来验证一下堆栈的使用. Input 首先输入整数t(1 <= t <= 10),代表测试的组数,以后是 t 组输入. 对于每组测试数据,第一行输入两个正整数 m(1 <= m &

SDUT-2088_数据结构实验之栈与队列十一:refresh的停车场

数据结构实验之栈与队列十一:refresh的停车场 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description refresh最近发了一笔横财,开了一家停车场.由于土地有限,停车场内停车数量有限,但是要求进停车场的车辆过多.当停车场满时,要进入的车辆会进入便道等待,最先进入便道的车辆会优先 进入停车场,而且停车场的结构要求只出去的车辆必须是停车场中最后进去的车辆.现告诉你停车场容量N以及命令数M,以及一些命令(Add num 表

SDUT-2449_数据结构实验之栈与队列十:走迷宫

数据结构实验之栈与队列十:走迷宫 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 一个由n * m 个格子组成的迷宫,起点是(1, 1), 终点是(n, m),每次可以向上下左右四个方向任意走一步,并且有些格子是不能走动,求从起点到终点经过每个格子至多一次的走法数. Input 第一行一个整数T 表示有T 组测试数据.(T <= 110) 对于每组测试数据: 第一行两个整数n, m,表示迷宫有n * m 个格子.(1

数据结构算法(1)--栈与队列

数据结构算法(1)--栈与队列 总结并记录学习数据结构过程中遇到的问题及算法. 一些常见算法: Note: 基础应用. 递归的非递归转化. 阶乘 递归实现: #include <iostream> using namespace std; int F(int n) { if (n == 0 || n == 1) return 1; else return n * F(n - 1); } int main() { int s; cin >> s; int result = F(s);

数据结构实验之栈与队列九:行编辑器

数据结构实验之栈与队列九:行编辑器 Description 一个简单的行编辑程序的功能是:接受用户从终端输入的程序或数据,并存入用户的数据区. 由于用户在终端上进行输入时,不能保证不出差错,因此,若在编辑程序中,“每接受一个字符即存入用户数据区”的做法显然不是最恰当的.较好的做法是,设立一个输入缓冲区,用以接受用户输入的一行字符,然后逐行存入用户数据区.允许用户输入出差错,并在发现有误时可以及时更正.例如,当用户发现刚刚键入的一个字符是错的时,可补进一个退格符"#",以表示前一个字符无

数据结构实验之栈与队列二:一般算术表达式转换成后缀式

数据结构实验之栈与队列二:一般算术表达式转换成后缀式 Description 对于一个基于二元运算符的算术表达式,转换为对应的后缀式,并输出之. Input 输入一个算术表达式,以‘#’字符作为结束标志. Output 输出该表达式转换所得到的后缀式. Sample Input a*b+(c-d/e)*f# Output ab*cde/-f*+ #include <stdio.h> #include <stdlib.h> char s[100005]; //分配栈的大小 int m

数据结构与算法-栈和队列

一.简介 众所周知,线性表是数据结构的基础,通常有两种实现方式:数组和链表.栈和队列是最常用的数据结构,它们基于线性表实现. 二.栈 定义:栈是限定仅在表尾进行插入和删除操作的线性表,即FILO. 栈被经常类比于弹夹,即先被压如弹夹的子弹最后被打出.根据线性表的实现方式得知,栈的实现方式有两种:数组实现和链表实现. 栈的数组实现: package basic.data_structure.cha01; /** * 栈:先进后出(FILO),只允许在栈顶操作元素 * 栈的基本操作: * 初始化栈.