数据结构期末复习(第三章 栈与队列)

数据结构期末复习(第三章 栈与队列)

个人感觉,这一章的内容不算特别难,主要是对上一章的链表之类的思想加以巩固;如果链表什么的没搞懂,学起来还是特别痛苦。不过学着学着也就悟了,不用太焦虑,我也是学着学着才慢慢摸索懂的。 说在前面,知识点总结中的代码一定一定一定要手敲一遍,过程中一定会遇到各种各样的问题,只看不动手很容易眼高手低! 还有,代码都是伪代码,提供思路用的,不要照着抄 原理之类的看不懂,其实敲一遍就理解了,实践出真知。

Part 1、知识点总结

栈和队列是两种应用非常广泛的数据结构,它们都来自线性表数据结构,都是“操作受限”的线性表。
栈在计算机的实现有多种方式:
◆ 硬堆栈:利用CPU中的某些寄存器组或类似的硬件或使用内存的特殊区域来实现。这类堆栈容量有限,但速度很快;
◆ 软堆栈:这类堆栈主要在内存中实现。堆栈容量可以达到很大。在实现方式上,又有动态方式和静态方式两种。
在这里插入图片描述

1.1.0 栈和队列的基本概念

栈和队列是两种特殊的线性表,它们的逻辑结构和线性表相同,只是其访问规则较线性表有更多的限制,故又称它们为访问受限的线性表

1.1.1 栈的基本概念

  • 栈(Stack):是限制在表的一端进行插入和删除操作的线性表。又称为后进先出LIFO (Last In First Out)或先进后出FILO (First In Last Out)线性表。
  • 栈顶(Top):允许进行插入、删除操作的一端,又称为表尾。用栈顶指针(top)来指示栈顶元素。
  • 栈底(Bottom):是固定端,又称为表头。
  • 空栈:当表中没有元素时称为空栈。

1.1.2 栈的顺序存储表示

栈的顺序存储结构简称为顺序栈,和线性表相类似,用一维数组来存储栈。根据数组是否可以根据需要增大,又可分为静态顺序栈和动态顺序栈。
◆ 静态顺序栈实现简单,但不能根据需要增大栈的存储空间;
◆ 动态顺序栈可以根据需要增大栈的存储空间,但实现稍为复杂。

1.1.2.1 栈的动态顺序存储表示

◆ 采用动态一维数组来存储栈。所谓动态,指的是栈的大小可以根据需要增加。
◆ 用bottom表示栈底指针,栈底固定不变的;栈顶则随着进栈和退栈操作而变化。用top(称为栈顶指针)指示当前栈顶位置。
◆ 用top=bottom作为栈空的标记,每次top指向栈顶数组中的下一个存储位置。
◆ 结点进栈:首先将数据元素保存到栈顶(top所指的当前位置),然后执行top加1,使top指向栈顶的下一个存储位置;
◆ 结点出栈:首先执行top减1,使top指向栈顶元素的存储位置,然后将栈顶元素取出

1.1.2.2 基本实现

  1. 栈的类型定义
#define  STACK_SIZE  100    /*  栈初始向量大小  */
#define STACKINCREMENT 10   /*  存储空间分配增量  */
#typedef  int  ElemType ;
typedef struct sqstack
{   ElemType  *bottom;     /*  栈不存在时值为NULL  */
ElemType  *top;      /*  栈顶指针  */
int   stacksize ;      /*  当前已分配空间,以元素为单位  */
}SqStack ;
  1. 栈的初始化
Status Init_Stack(void)
{   SqStack  S ;
S.bottom=(ElemType *)malloc(STACK_SIZE *sizeof(ElemType));
if (! S.bottom) return  ERROR;
S.top=S.bottom ;    /*  栈空时栈顶和栈底指针相同  */
S. stacksize=STACK_SIZE; 
return OK ;
}
  1. 压栈(元素进栈)
Status push(SqStack S , ElemType  e)
   {  if  (S.top-S.bottom>=S. stacksize-1) 
{   S.bottom=(ElemType *)realloc((S. STACKINCREMENT+STACK_SIZE) *sizeof(ElemType));   /*  栈满,追加存储空间  */
if (! S.bottom)  return  ERROR; 
S.top=S.bottom+S. stacksize ;
S. stacksize+=STACKINCREMENT ;
}  
*S.top=e;  S.top++ ; /*  栈顶指针加1,e成为新的栈顶 */
return OK;
}
  1. 弹栈(元素出栈)
Status pop( SqStack   S, ElemType  *e )      
/*弹出栈顶元素*/
{   if ( S.top== S.bottom )  
return ERROR ;       /*  栈空,返回失败标志  */
S.top-- ; e=*S. top ;  
return  OK ; 
} 

1.1.2.3 栈的静态顺序存储表示

采用静态一维数组来存储栈。
栈底固定不变的,而栈顶则随着进栈和退栈操作变化的,

◆ 栈底固定不变的;栈顶则随着进栈和退栈操作而变化,用一个整型变量top(称为栈顶指针)来指示当前栈顶位置。
◆ 用top=0表示栈空的初始状态,每次top指向栈顶在数组中的存储位置。
◆ 结点进栈:首先执行top加1,使top指向新的栈顶位置,然后将数据元素保存到栈顶(top所指的当前位置)。
◆ 结点出栈:首先把top指向的栈顶元素取出,然后执行top减1,使top指向新的栈顶位置。
在这里插入图片描述

1.1.2.4 基本操作的实现

  1. 栈的类型定义
# define  MAX_STACK_SIZE  100      /*  栈向量大小  */
# typedef  int  ElemType ;
typedef struct  sqstack
{  ElemType   stack_array[MAX_STACK_SIZE] ;
int  top;
}SqStack ;
  1. 栈的初始化
SqStack Init_Stack(void)
{    SqStack  S ;
S.bottom=S.top=0 ;  return(S) ;
}
  1. 压栈(元素进栈)
Status push(SqStack S , ElemType  e)
   /*  使数据元素e进栈成为新的栈顶  */
{  if  (S.top==MAX_STACK_SIZE-1) 
return  ERROR;      /*  栈满,返回错误标志    */
S.top++ ;      /*  栈顶指针加1  */
S.stack_array[S.top]=e  ;   /* e成为新的栈顶  */
return OK;        /*  压栈成功    */
}
  1. 弹栈(元素出栈)
Status  pop( SqStack   S, ElemType  *e )
      /*弹出栈顶元素*/
{  if ( S.top==0 )
return ERROR ;       /*  栈空,返回错误标志    */
*e=S.stack_array[S.top] ;  
S.top-- ;  
return OK ;  
}

1.1.2.5 注意

当栈满时做进栈运算必定产生空间溢出,简称“上溢”。上溢是一种出错状态,应设法避免。
当栈空时做退栈运算也将产生溢出,简称“下溢”。下溢则可能是正常现象,因为栈在使用时,其初态或终态都是空栈,所以下溢常用来作为控制转移的条件。

1.2.2 链栈

在这里插入图片描述
栈的链式存储结构称为链栈,是运算受限的单链表。其插入和删除操作只能在表头位置上进行。因此,链栈没有必要像单链表那样附加头结点,栈顶指针top就是链表的头指针。

注意!不是偷懒不是偷懒不是偷懒!链栈几乎和之前的单链表一模一样,定义上几乎只是改个名字,操作上也没什么可多说的,会写就行!我这可不是偷懒嗷!不是!

1.3 栈与递归调用的实现

栈的另一个重要应用是在程序设计语言中实现递归调用。
递归调用:一个函数(或过程)直接或间接地调用自己本身,简称递归(Recursive)。
递归是程序设计中的一个强有力的工具。因为递归函数结构清晰,程序易读,正确性很容易得到证明。
为了使递归调用不至于无终止地进行下去,实际上有效的递归调用函数(或过程)应包括两部分:递推规则(方法),终止条件。
为保证递归调用正确执行,系统设立一个“递归工作栈”,作为整个递归调用过程期间使用的数据存储区。
每一层递归包含的信息如:参数、局部变量、上一层的返回地址构成一个“工作记录” 。每进入一层递归,就产生一个新的工作记录压入栈顶;每退出一层递归,就从栈顶弹出一个工作记录。
从被调函数返回调用函数的一般步骤:

  1. 若栈为空,则执行正常返回。
  2. 从栈顶弹出一个工作记录。
  3. 将“工作记录”中的参数值、局部变量值赋给相应的变量;读取返回地址。
  4. 将函数值赋给相应的变量。
  5. 转移到返回地址。

2.1.0 队列

只允许在一端插入,在另一端删除的线性表(感受一下什么叫受限的线性表)

2.1.1 队列的基本概念

队列(Queue):也是运算受限的线性表。是一种先进先出(First In First Out ,简称FIFO)的线性表。只允许在表的一端进行插入,而在另一端进行删除。
队首(front) :允许进行删除的一端称为队首。
队尾(rear) :允许进行插入的一端称为队尾。
  例如:排队购物。操作系统中的作业排队。先进入队列的成员总是先离开队列。
  队列中没有元素时称为空队列。在空队列中依次加入元素a1, a2, …, an之后,a1是队首元素,an是队尾元素。显然退出队列的次序也只能是a1, a2, …, an ,即队列的修改是依先进先出的原则进行的
  在这里插入图片描述

2.2.2 队列的顺序表示和实现

利用一组连续的存储单元(一维数组) 依次存放从队首到队尾的各个元素,称为顺序队列。
对于队列,和顺序栈相类似,也有动态和静态之分.
类型定义如下:

#define  MAX_QUEUE_SIZE   100
typedef  struct  queue
{  ElemType   Queue_array[MAX_QUEUE_SIZE] ;
int   front ;
int  rear ;
}SqQueue;

设立一个队首指针front ,一个队尾指针rear ,分别指向队首和队尾元素。
◆ 初始化:front=rear=0。
◆ 入队:将新元素插入rear所指的位置,然后rear加1。
◆ 出队:删去front所指的元素,然后加1并返回被删元素。
◆ 队列为空:front=rear。
◆ 队满:rear=MAX_QUEUE_SIZE-1或front=rear。
在非空队列里,队首指针始终指向队头元素,而队尾指针始终指向队尾元素的下一位置。
顺序队列中存在“假溢出”现象。因为在入队和出队操作中,头、尾指针只增加不减小,致使被删除元素的空间永远无法重新利用。因此,尽管队列中实际元素个数可能远远小于数组大小,但可能由于尾指针巳超出向量空间的上界而不能做入队操作。该现象称为假溢出。如图3-6所示是数组大小为5的顺序队列中队首、队尾指针和队列中元素的变化情况。
在这里插入图片描述

2.2.3 循环队列

为充分利用向量空间,克服上述“假溢出”现象的方法是:将为队列分配的向量空间看成为一个首尾相接的圆环,并称这种队列为循环队列(Circular Queue)。
在循环队列中进行出队、入队操作时,队首、队尾指针仍要加1,朝前移动。只不过当队首、队尾指针指向向量上界(MAX_QUEUE_SIZE-1)时,其加1操作的结果是指向向量的下界0。
这种循环意义下的加1操作可以描述为:

if  (i+1==MAX_QUEUE_SIZE)   i=0;
else     i++ ;

其中: i代表队首指针(front)或队尾指针(rear)
用模运算可简化为:

i=(i+1)%MAX_QUEUE_SIZE ;

· 显然,为循环队列所分配的空间可以被充分利用,除非向量空间真的被队列元素全部占用,否则不会上溢。因此,真正实用的顺序队列是循环队列。
入队时尾指针向前追赶头指针,出队时头指针向前追赶尾指针,故队空和队满时头尾指针均相等。因此,无法通过front=rear来判断队列“空”还是“满”。解决此问题的方法是:约定入队前,测试尾指针在循环意义下加1后是否等于头指针,若相等则认为队满。
◆ rear所指的单元始终为空。
◆ 循环队列为空:front=rear 。
◆ 循环队列满:(rear+1)%MAX_QUEUE_SIZE =front。

2.2.3.1 循环队列的基本操作

1 循环队列的初始化

SqQueue Init_CirQueue(void)
{  SqQueue  Q ;
Q.front=Q.rear=0;  return(Q) ;
}

2 入队操作

Status Insert_CirQueue(SqQueue  Q , ElemType  e)
  /*  将数据元素e插入到循环队列Q的队尾  */
{  if  ((Q.rear+1)%MAX_QUEUE_SIZE== Q.front)
return  ERROR;      /*  队满,返回错误标志    */
Q.Queue_array[Q.rear]=e ;   /*  元素e入队  */
Q.rear=(Q.rear+1)% MAX_QUEUE_SIZE ; 
/*  队尾指针向前移动  */
return OK;        /*  入队成功    */
}

3 出队操作

Status Delete_CirQueue(SqQueue  Q, ElemType  *x )
   /*  将循环队列Q的队首元素出队  */
{   if  (Q.front+1== Q.rear)
return ERROR ;       /*  队空,返回错误标志    */
*x=Q.Queue_array[Q.front] ;  /* 取队首元素 */
Q.front=(Q.front+1)% MAX_QUEUE_SIZE ;
     /*  队首指针向前移动  */
return OK ;
}

2.2.4 队列的链式表示和实现

队列的链式存储结构简称为链队列,它是限制仅在表头进行删除操作和表尾进行插入操作的单链表。
需要两类不同的结点:数据元素结点,队列的队首指针和队尾指针的结点。
数据元素结点类型定义:

typedef struct Qnode
{  ElemType    data ;
struct Qnode  *next ;
}QNode ;

指针结点类型定义:

typedef struct link_queue
{   QNode  *front ,  *rear ;
}Link_Queue ;
2.2.4.1 链队运算及指针变化

链队的操作实际上是单链表的操作,只不过是删除在表头进行,插入在表尾进行。插入、删除时分别修改不同的指针。
在这里插入图片描述

2.2.4.2 链队列的基本操作

⑴ 链队列的初始化

LinkQueue *Init_LinkQueue(void)
{  LinkQueue  *Q ;  QNode  *p ;
p=(QNode *)malloc(sizeof(QNode)) ; /* 开辟头结点 */
p->next=NULL ;
Q=(LinkQueue  *)malloc(sizeof(LinkQueue)) ; 
        /*  开辟链队的指针结点  */
Q.front=Q.rear=p ; 
return(Q) ;
}

⑵ 链队列的入队操作
在已知队列的队尾插入一个元素e ,即修改队尾指针(Q.rear)。

Status  Insert_CirQueue(LinkQueue  *Q , ElemType  e)
      /*  将数据元素e插入到链队列Q的队尾  */
{   p=(QNode *)malloc(sizeof(QNode)) ;
if (!p)  return  ERROR;
/*  申请新结点失败,返回错误标志 */
p->data=e ; p->next=NULL ;       /*  形成新结点 */
Q.rear->next=p ;  Q.rear=p ;  /*  新结点插入到队尾  */
return OK;
}

⑶ 链队列的出队操作
Status Delete_LinkQueue(LinkQueue *Q, ElemType *x)
{ QNode p ;
if (Q.front==Q.rear) return ERROR ; /
队空 /
p=Q.front->next ; /
取队首结点 */
x=p->data ;
Q.front->next=p->next ; /
修改队首指针 /
if (p==Q.rear) Q.rear=Q.front ;
/
当队列只有一个结点时应防止丢失队尾指针 */
free§ ;
return OK ;
}
⑶ 链队列的出队操作

Status  Delete_LinkQueue(LinkQueue  *Q, ElemType *x)
   {   QNode *p ;
if  (Q.front==Q.rear)  return ERROR ;    /*  队空  */
p=Q.front->next ;   /*  取队首结点  */
*x=p->data ; 
Q.front->next=p->next ;      /*  修改队首指针  */
if  (p==Q.rear)  Q.rear=Q.front ;
     /*  当队列只有一个结点时应防止丢失队尾指针  */
    free(p) ;   
return OK ; 
}

⑷ 链队列的撤消

void  Destroy_LinkQueue(LinkQueue  *Q )
   /*  将链队列Q的队首元素出队  */
{   while  (Q.front!=NULL)
{  Q.rear=Q.front->next;   
      /*  令尾指针指向队列的第一个结点   */
free(Q.front);      /*  每次释放一个结点  */ 
    /*  第一次是头结点,以后是元素结点  */
Q.ront=Q.rear;
}
}

3 关键问题

  • 栈虽然是一种后进先出的顺序存取结构,但是顺序存取和顺序存储并不一样;顺序存取指只能存或逐个取结构中的元素,数据存储是指利用一个连续的空间相继存放结构中的元素。

PPT课后题

1 设有一个栈,元素进栈的次序为a, b, c。问经过栈操作后可以得到哪些输出序列?
2 循环队列的优点是什么?如何判断它的空和满?
3 设有一个静态顺序队列,向量大小为MAX,判断队列为空的条件是什么?队列满的条件是什么?
4 设有一个静态循环队列,向量大小为MAX,判断队列为空的条件是什么?队列满的条件是什么?
5 利用栈的基本操作,写一个返回栈S中结点个数的算法int StackSize(SeqStack S) ,并说明S为何不作为指针参数的算法?
6 一个双向栈S是在同一向量空间内实现的两个栈,它们的栈底分别设在向量空间的两端。试为此双向栈设计初始化InitStack(S) ,入栈Push(S,i,x),出栈Pop(S,i,x)算法,其中i为0或1 ,用以表示栈号。
7 设Q[0,6]是一个静态顺序队列,初始状态为front=rear=0,请画出做完下列操作后队列的头尾指针的状态变化情况,若不能入对,请指出其元素,并说明理由。
a, b, c, d入队
a, b, c出队
i , j , k , l , m入队
d, i出队
n, o, p, q, r入队
8 假设Q[0,5]是一个循环队列,初始状态为front=rear=0,请画出做完下列操作后队列的头尾指针的状态变化情况,若不能入对,请指出其元素,并说明理由。
d, e, b, g, h入队
d, e出队
i , j , k , l , m入队
b出队
n, o, p, q, r入队

自己康的一点题

  1. 当利用大小为n的数组顺序存储一个栈时,假定用top == n表示栈空,则向这个栈插入一个元素时,首先应执行 top-- 语句修改top指针。
  2. 循环队列判断队满条件:Q.front == (Q.rear + 1)% maxsize
  3. 设循环队列的存储容量为maxsize,队头和队尾指针分别为front和rear。若有一个循环队列Q,可用(Q.rear - Q.front + maxsize)%maxsize 来计算元素个数
  4. 将递归算法转换成对应的非递归算法时,除了单项递归和尾递归的情况外,通常需要使用栈保存中间结果
  5. 一个递归算法必须包括结束条件和递归部分
  6. 栈和队列共同点是允许在端点处进行操作线性表

Part 2、代码

//共享栈
#include "stdio.h"
#define Maxsize 20
#define error -1
#define ok 1
typedef int ElemType;
typedef struct{
	ElemType data[Maxsize];
	int top0;
	int top1;
}shstack;
void InitStack(shstack *s)
{
	s->top0=-1;
	s->top1=Maxsize;
}
int Push(shstack *s,int i,ElemType x)
{
	if(s->top1==s->top0+1)
	return error;
	if(i==0)
	{
		s->top0++;
		s->data[s->top0]=x;
	}
	else if(i==1)
	{
		s->top1--;
		s->data[s->top1]=x;
	}
	else return error;
	return ok;
}
int Pop(shstack *s,int i,ElemType x)
{
	if(i==0)
	{
		if(s->top0==-1)
		return error;
	}
	else if(i==1)
	{
		if(s->top1==Maxsize)
		return error;
	}
	else return error;
	if(i==0)
	{
		x=s->data[s->top0];
		s->top0--;
	}
	else
	{
		x=s->data[s->top1];
		s->top1++;
	}
	printf("The number popped is %d\n",x);
	return ok;
}
int main()
{
	shstack s;
	int tmp,i,x,boolean;
	InitStack(&s);
	printf("The stack has been created successfully!\n");
	printf("0->End the program.\n");
	printf("1->Push new numbers.\n");
	printf("2->Pop numbers.\n");
	while(1)
	{
		scanf("%d",&tmp);
		if(tmp==0) break;
		else if(tmp==1)
		{
			printf("Please input where you want insert and the number you want to push:\n");
			scanf("%d %d",&i,&x);
			boolean=Push(&s,i,x);
			if(boolean==error) printf("ERROR!\n");
			else
			printf("Pushed successfully!\n");
		}
		else if(tmp==2)
		{
			printf("Please input which stack you want to pop the number:\n");
			scanf("%d",&i);
			boolean=Pop(&s,i,x);
			if(boolean==error) printf("ERROR!\n");
		}
		else
		{
			printf("ERROR!\n");
		}
	}
	printf("Thanks for using.\n");
	return 0;
}
//括号匹配
#include "stdio.h"
#include "string.h"
#define Maxsize 20
#define error -1
#define ok 1
typedef char ElemType;
typedef struct{
	ElemType data[Maxsize];
	int top;
}shstack;
void InitStack(shstack *s)
{
	s->top=-1;
}
int StackEmpty(shstack *s)
{
	if(s->top==-1)
	return ok;
	else return error;
}
int Push(shstack *s,ElemType x)
{
	if(s->top==Maxsize)
	return error;
	s->top++;
	s->data[s->top]=x;
	return ok;
}
int Pop(shstack *s,ElemType x)
{
	if(s->top==-1)
	return error;
	x=s->data[s->top];
	s->top--;
	return x;
}
int check(char string[],int len)
{
	shstack s;
	InitStack(&s);
	int i;
	char tmp;
	for(i=0;i<len;i++)
	{
		if(string[i]=='('||string[i]=='['||string[i]=='{'||string[i]=='<')
		Push(&s,string[i]);
		else
		{
			if(StackEmpty(&s)==ok) return error;
			tmp=Pop(&s,tmp);
			if(string[i]==')'&&tmp!='(')
			return error;
			if(string[i]==']'&&tmp!='[')
			return error;
			if(string[i]=='}'&&tmp!='{')
			return error;
			if(string[i]=='>'&&tmp!='<')
			return error;
		}
	}
	return ok;
}
int main()
{
	char string[100],tmp;
	int len,i=0;
	while(1)
	{
		scanf("%c",&tmp);
		if(tmp!='{'&&tmp!='}'&&tmp!='['&&tmp!=']'&&tmp!='('&&tmp!=')'&&tmp!='\n'&&tmp!='<'&&tmp!='>')
		{
			printf("ERROR!\n");
			return 0;
		}
		if(tmp!='\n')
		{
			string[i]=tmp;
			i++;
		}
		else{
			string[i]='\0';
			break;
		}
	}
	len=strlen(string);
	int answer;
	answer=check(string,len);
	if(answer==error)
	printf("Failed!\n");
	else if(answer==ok)
	printf("Succeed!\n");
	return 0;
}
//求结点个数
#include "stdio.h"
#include "stdlib.h"
#define Maxsize 50
#define error -1
#define ok 1
typedef int ElemType;
typedef struct{
	ElemType data[Maxsize];
	int top;
}SeqStack;
void InitStack(SeqStack *s)
{
	s->top=-1;
}
int Push(SeqStack *s,ElemType x)
{
	if(s->top==Maxsize)
	return error;
	s->top++;
	s->data[s->top]=x;
	return ok;
}
int StackSize(SeqStack S)
{
	int len=0;
	len=S.top+1;
	return len;
}
int main()
{
	SeqStack s;
	InitStack(&s);
	int tmp,e,len;
	printf("0->End the Program.\n");
	printf("1->Push new numbers.\n");
	printf("2->Get the length of stack.\n");
	while(1)
	{
		scanf("%d",&tmp);
		if(tmp==0) break;
		else if(tmp==1)
		{
			scanf("%d",&e);
			Push(&s,e);
		}
		else if(tmp==2)
		{
			len=StackSize(s);
			printf("The length of stack is %d\n",len);
		}
		else printf("ERROR!");
	}
	return 0;
}
//队列逆序
#include "stdio.h"
#include "stdlib.h"
#define Maxsize 50
#define error -1
#define ok 1
typedef int ElemType;
typedef struct {
	ElemType data[Maxsize];
	int top;
}SeqStack;
typedef struct {
	ElemType data[Maxsize];
	int front, rear, size;
}SqQueue;
void InitStack(SeqStack* s)
{
	s->top = -1;
}
int Push(SeqStack* s, ElemType x)
{
	if (s->top == Maxsize)
		return error;
	s->top++;
	s->data[s->top] = x;
	return ok;
}
int StackSize(SeqStack S)
{
	int len = 0;
	len = S.top + 1;
	return len;
}
int Pop(SeqStack* s, ElemType x)
{
	if (s->top == -1)
		return error;
	x = s->data[s->top];
	s->top--;
	return x;
}
void create(SqQueue* Q)
{
	Q->size = 0;
	Q->front = 0;
	Q->rear = 0;
}
int EnQueue(SqQueue* Q, ElemType e)
{
	if (Q->size == Maxsize) return error;
	Q->data[Q->rear] = e;
	Q->rear = (Q->rear + 1) % Maxsize;
	Q->size++;
	return ok;
}
int DeQueue(SqQueue* Q, ElemType e)
{
	if (Q->rear == Q->front) return error;
	e = Q->data[Q->front];
	Q->front = (Q->front + 1) % Maxsize;
	return e;
}
void print(SqQueue* Q, int len)
{
	int i;
	for (i = 0;i < len;i++)
	{
		printf("%d ", Q->data[Q->front + i]);
	}
}
int main()
{
	SeqStack s;
	InitStack(&s);
	SqQueue Q;
	create(&Q);
	int tmp, len = 0, i;
	printf("Please input numbers until '9999' is inputed.\n");
	while (1)
	{
		scanf("%d", &tmp);
		if (tmp == 9999) break;
		EnQueue(&Q, tmp);
		len++;
	}
	for (i = 0;i < len;i++)
	{
		tmp = DeQueue(&Q, tmp);
		Push(&s, tmp);
	}
	create(&Q);
	for (i = 0;i < len;i++)
	{
		tmp = Pop(&s, tmp);
		EnQueue(&Q, tmp);
	}
	print(&Q, len);
	return 0;
}

Part 3、总结

感觉自己也看了蛮多题的,但是总觉得都比较基础,没必要写到帖子里…到头来就加了几个题进去。这一块的重点还是巩固链表吧,因为不懂链表是不可能独立敲出来链栈的。
最低要求就是能独立敲栈的顺序存储和链式存储,至少得有基本的功能;
队列也要能敲出来带基本功能的。
在此基础上敲一下括号匹配、双向队列之类的综合性的代码,帮助会大一点。
代码都是很早之前敲的,很多地方现在看的也高血压(但是懒得改…能跑没bug就是阔以的),仅供参考,提供思路
知识点里的代码还是算法那一类的,伪代码,仅提供思路。第一遍敲可以参考一下,有bug就debug一下,要成为一个成熟的程序员(雾)
万变不离其宗,栈和队列无非就是在线性表和链表的基础上加一些条件限制,本质上都是一样的。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赤赤赤赤赤赤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值