05 堆棧和隊列


堆棧和隊列

一、棧

1.定義

​ 棧是一種滿足后進先出的數據結構;例:死胡同

  1. 允許進行插入、刪除操作的一端稱為棧頂 top
  2. 表的另一端稱為棧底
  3. 當棧中沒有數據元素時,稱為空棧
  4. 棧的插入操作通常稱為進棧或入棧
  5. 棧的刪除操作通常稱為退棧或出棧
void InitStack(SqStack *&s);
void DestroyStack(SqStack *&s);
bool StackEmpty(SqStack *s);
bool Push(SqStack *&s,ElemType e);
bool Pop(SqStack *&s,ElemType &e);
bool GetTop(SqStack *s,ElemType &e);

2.類型

①順序棧
②鏈棧

2.1順序棧

順序棧四要素:
①棧空條件:top=-1
②棧滿條件:top=MaxSize - 1
③進棧操作:top++;將e放在棧頂
④退棧操作:從top取出;top--

//順序棧基本運算算法
#include <stdio.h>
#include <malloc.h>
#define MaxSize 100
typedef char ElemType;
typedef struct 
{	
	ElemType data[MaxSize];
	int top;//棧指針
} SqStack;//順序棧類型
void InitStack(SqStack *&s)
{
	s=(SqStack *)malloc(sizeof(SqStack));
	s->top=-1;//top為下標,始終指向棧頂元素;在以數組構成的棧中,初始值為-1,自加一次則指向下標為0的元素
} 
void DestroyStack(SqStack *&s)
{
	free(s);
}
bool StackEmpty(SqStack *s)
{
	return(s->top==-1);
}
bool Push(SqStack *&s,ElemType e)
{
	if (s->top==MaxSize-1)//棧滿的情況,即棧上溢出
		return false;
	s->top++;
	s->data[s->top]=e;
	return true;
}
bool Pop(SqStack *&s,ElemType &e)
{
	if (s->top==-1)//棧為空的情況,即棧下溢出
		return false;
	e=s->data[s->top];
	s->top--;
	return true;
} 
bool GetTop(SqStack *s,ElemType &e)
{
	if (s->top==-1)//棧為空的情況,即棧下溢出
		return false;
	e=s->data[s->top];
	return true;
}

2.2 鏈棧

//鏈棧基本運算算法
#include <stdio.h>
#include <malloc.h>
typedef char ElemType;
typedef struct linknode
{	
	ElemType data;				//數據域
	struct linknode *next;		//指針域
} LinkStNode;					//鏈棧類型
void InitStack(LinkStNode *&s)
{
	s=(LinkStNode *)malloc(sizeof(LinkStNode));
	s->next=NULL;
}
void DestroyStack(LinkStNode *&s)
{
	LinkStNode *p=s->next;
	while (p!=NULL)
	{	
		free(s);
		s=p;
		p=p->next;
	}
	free(s);	//s指向尾結點,釋放其空間
}
bool StackEmpty(LinkStNode *s)
{
	return(s->next==NULL);
}
void Push(LinkStNode *&s,ElemType e)
{	LinkStNode *p;
	p=(LinkStNode *)malloc(sizeof(LinkStNode));
	p->data=e;				//新建元素e對應的結點p
	p->next=s->next;		//插入p結點作為開始結點
	s->next=p;
}
bool Pop(LinkStNode *&s,ElemType &e)
{	LinkStNode *p;
	if (s->next==NULL)		//棧空的情況
		return false;
	p=s->next;				//p指向開始結點
	e=p->data;
	s->next=p->next;		//刪除p結點
	free(p);				//釋放p結點
	return true;
}
bool GetTop(LinkStNode *s,ElemType &e)
{	if (s->next==NULL)		//棧空的情況
		return false;
	e=s->next->data;
	return true;
}

3.表達式

算數表達式=中綴表達式【考慮運算符優先性】
二叉樹畫法:【根據優先級順序,找運算符;整體上()> 乘除 > 加減 ,局部上從左到右)
①找到符號兩邊的兩個數
②先寫符號,再寫數
③根據中序,依次合並,畫出二叉樹

轉后綴表達式:
1.遇到操作數:直接輸出
2.棧為空時,遇到運算符,直接入棧
3.遇到左括號:將其入棧
4.遇到右括號:執行出棧操作,直到彈出棧的是左括號,括號不輸出。
5.遇到其他運算符:加減乘除:彈出所有優先級大於或者等於該運算符的棧頂元素,然后將該運算符入棧
6.最終將棧中的元素依次出棧,輸出。

簡便方法:
①根據優先級順序中綴符號兩邊,兩兩結合,用括號括起來。
②前綴則把符號挪到括號左側,后綴則挪到右側。
③最后括號都去掉

前綴與后綴【不用考慮運算符優先性】
后綴表達式---->二叉樹以后序輸出
二叉樹畫法:①找到符號的前兩個數
②先寫符號,再寫數
③根據后序,依次合並,畫出二叉樹
前綴表達式---->二叉樹以前序輸出

4.出入棧序列

入棧序列為1,2,3,4,5,6,則不可能的序列
棧頂有高位元素后,+出棧的首先得是高位元素;

5.進制轉化

高進制->低進制,除法
余數依次進棧,依次輸出即可

6.括號匹配

二、隊列

1.順序隊列基本代碼

(1) 入隊時隊尾指針前進1:(rear+1)%QueueSize

(2) 出隊時隊頭指針前進1:(front+1)%QueueSize

(3) 隊列長度:(rear-front+QueueSize)%QueueSize

​ 現有一循環隊列,其隊頭指針為front,隊尾指針為rear;循環隊列長度為N。其隊內有效長度為?(假設隊頭不存放數據)

​ 答案:(rear-front+N)%N

(4) 隊空和隊滿的條件

​ 為了區分隊空還是堆滿的情況,有多種處理方式:

方式1: 犧牲一個單元來區分隊空和隊滿,入隊時少用一個隊列單元,即約定以"隊頭指針在隊尾指針的下一位置作為隊滿的標志"。

​ 隊滿條件為:(rear+1)%QueueSize==front

​ 隊空條件為:front==rear

​ 隊列長度為:(rear-front+QueueSize)%QueueSize

方式2: 增設表示隊列元素個數的數據成員size,此時,隊空和隊滿時都有front==rear。

​ 隊滿條件為:size==QueueSize

​ 隊空條件為:size==0

方式3: 增設tag數據成員以區分隊滿還是隊空

​ tag表示0的情況下,若因刪除導致front==rear,則隊空;

​ tag等於1的情況,若因插入導致front==rear則隊滿

2.類型

①順序隊列(非環形)
②順序隊列(環形)
③鏈隊

2.1 順序隊列(非環形)

//順序隊列(非環形隊列)基本運算算法
#include <stdio.h>
#include <malloc.h>
#define MaxSize 100
typedef char ElemType;
typedef struct 
{	
	ElemType data[MaxSize];
	int front,rear;						//隊頭和隊尾指針
} SqQueue;
void InitQueue(SqQueue *&q)
{	q=(SqQueue *)malloc (sizeof(SqQueue));
	q->front=q->rear=-1;
}
void DestroyQueue(SqQueue *&q)			//銷毀隊列
{
	free(q);
}
bool QueueEmpty(SqQueue *q)				//判斷隊列是否為空
{
	return(q->front==q->rear);
}
bool enQueue(SqQueue *&q,ElemType e)	//進隊
{	if (q->rear==MaxSize-1)				//隊滿上溢出
		return false;					//返回假
	q->rear++;							//隊尾增1
	q->data[q->rear]=e;					//rear位置插入元素e
	return true;						//返回真
}
bool deQueue(SqQueue *&q,ElemType &e)	//出隊
{	if (q->front==q->rear)				//隊空下溢出
		return false;
	q->front++;
	e=q->data[q->front];
	return true;
}

2.2 順序隊列(環形)

//順序隊列(環形隊列)基本運算算法
#include <stdio.h>
#include <malloc.h>
#define MaxSize 100
typedef char ElemType;
typedef struct 
{	
	ElemType data[MaxSize];
	int front,rear;		//隊首和隊尾指針
} SqQueue;
void InitQueue(SqQueue *&q)
{	q=(SqQueue *)malloc (sizeof(SqQueue));
	q->front=q->rear=0;
}
void DestroyQueue(SqQueue *&q)
{
	free(q);
}
bool QueueEmpty(SqQueue *q)
{
	return(q->front==q->rear);
}
bool enQueue(SqQueue *&q,ElemType e)
{	if ((q->rear+1)%MaxSize==q->front)	//隊滿上溢出
		return false;
	q->rear=(q->rear+1)%MaxSize;
	q->data[q->rear]=e;
	return true;
}
bool deQueue(SqQueue *&q,ElemType &e)
{	if (q->front==q->rear)		//隊空下溢出
		return false;
	q->front=(q->front+1)%MaxSize;
	e=q->data[q->front];
	return true;
}

2.3 鏈隊

同樣包括單鏈表的隊列,循環鏈表隊列

//鏈隊運算算法
#include <stdio.h>
#include <malloc.h>
typedef char ElemType;
typedef struct DataNode
{	
	ElemType data;
	struct DataNode *next;
} DataNode;				//鏈隊數據結點類型
typedef struct
{	
	DataNode *front;
	DataNode *rear;
} LinkQuNode;			//鏈隊類型
void InitQueue(LinkQuNode *&q)
{	
	q=(LinkQuNode *)malloc(sizeof(LinkQuNode));
	q->front=q->rear=NULL;
}
void DestroyQueue(LinkQuNode *&q)
{
	DataNode *p=q->front,*r;//p指向隊頭數據結點
	if (p!=NULL)			//釋放數據結點占用空間
	{	r=p->next;
		while (r!=NULL)
		{	free(p);
			p=r;r=p->next;
		}
	}
	free(p);
	free(q);				//釋放鏈隊結點占用空間
}
bool QueueEmpty(LinkQuNode *q)
{
	return(q->rear==NULL);
}
void enQueue(LinkQuNode *&q,ElemType e)
{	DataNode *p;
	p=(DataNode *)malloc(sizeof(DataNode));
	p->data=e;
	p->next=NULL;
	if (q->rear==NULL)		//若鏈隊為空,則新結點是隊首結點又是隊尾結點
		q->front=q->rear=p;
	else
	{	q->rear->next=p;	//將p結點鏈到隊尾,並將rear指向它
		q->rear=p;
	}
}
bool deQueue(LinkQuNode *&q,ElemType &e)
{	DataNode *t;
	if (q->rear==NULL)		//隊列為空
		return false;
	t=q->front;				//t指向第一個數據結點
	if (q->front==q->rear)  //隊列中只有一個結點時
		q->front=q->rear=NULL;
	else					//隊列中有多個結點時
		q->front=q->front->next;
	e=t->data;
	free(t);
	return true;
}

三、其它算法

3.1兩個棧實現一個隊列


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM