1. 程式人生 > >棧與佇列 -- 增、查、改、刪操作

棧與佇列 -- 增、查、改、刪操作

1. 棧

棧是一種只能在一端進行插入或刪除操作的線性表 其中允許進行插入或刪除操作的一端稱為棧頂(Top) 棧頂由一個棧頂指標的位置指示器(其實是1個變數,對於順序棧就是記錄棧頂元素所在陣列位置標號的一個整型變數,對於鏈式棧就是記錄棧頂元素所在結點地址的指標)它是動態變換的。 表的另一端稱為棧底,棧底是固定不變的。 棧的插入和刪除操作一般稱為入棧和出棧。 特點:先進後出(FILO) 儲存結構:順序棧和鏈式棧 棧是一種在操作上稍加限制的線性表,即棧的本質是線性表; 數學性質: 當n個元素以某種順序進棧,並且可在任意時刻出棧時,所獲得的元素排序的數目N恰好滿足函式

N=1n+1C2nnN=\frac{1}{n+1}C_{2n}^{n}

01. 順序棧

棧空狀態:st.top == -1或st.top == 0 棧滿狀態:st.top ==maxsize -1

因為陣列下標從0開始,maxsize -1 為棧滿時,棧頂元素在陣列中的位置

上溢:棧滿繼續入棧 下溢:棧空的時候繼續出棧所造成的

元素x進棧操作:

++(st.top);
st.data[st.top]=x ;

必須先移動指標,再進入元素 元素x出棧操作:

x = st.data[st.top] ;
--(st.top);

1) 定義棧

typedef  struct
{
	int  data[maxsize];
	int  top;
}SqStack;

2) 初始化棧

void  initStack( SqStack  &st)
{
	st.top = -1;
}

3) 判斷棧空

int  isEmpty(SqStack  st)
{
	if(st.top  ==-1)
		return  1;
	else
		return  0;
}

4) 進棧

int  push(SqStack  &st , int x)
{
	if(st.top == maxsize -1)
		return  0;

	++(st.top);
	st.data[st.top] = x;
		return  1;
}

5) 出棧

int  pop
(SqStack &st ,int &x) { if(st.top == -1) return 0; x = st.data[st.top]; --(st.top); return 1; }

6) 簡化操作

//定義並初始化
int  stack[maxsize];
int  top = -1;


//元素x進棧
stack[++top] == x;

//元素x出棧
x = stack[top--];

02、 鏈棧

棧空狀態:lst->next == NULL; 棧滿狀態:不存在棧滿狀態 元素進棧(由p指標所指)

	p->next = lst->next;
	lst->next = p

元素出棧(出棧元素儲存在x中)

	p = last->next;
	x = p->data;
	lst->next = p->next;
	free(p)

1) 鏈棧結點定義

typedef  struct  LNode
{
	int  data;
	struct  LNode *next;
}LNode;

2) 初始化鏈棧

void  initStack(LNode  *&lst)
{
	lst = (LNode *)malloc(sizeof(LNode));
	lst->next = NULL;
}

3) 判斷棧空

int  isEmpty(LNode  *lst)
{
	if(lst->next == NULL)
		return 1;
	else 
		return 0;
}

4) 進棧(頭插法)

void  push(LNode *lst , int x)
{
	LNode  *p;
	p = (LNode *)malloc(sizeof(LNode));
	p->next = NULL;

	p->data = x;
	p->next = lst->next;
	p->next = p;
}

5) 出棧

int  pop(LNode *lst , int &x)
{
	LNode  *p;
	if(lst->next == NULL)
		return 0;
	p = lst->next;
	x = p->data;
	lst->next = p->next;
	free(p);
	return  1;
}

3. 佇列

定義:佇列是一種操作受限的線性表, 其限制為僅允許在標的一端進行插入,在表的另一端刪除, 可進行插入的一端稱為隊尾,可進行刪除的一端稱為隊頭; 向佇列中插入元素稱為進隊,新元素進隊後就成為新的隊尾元素; 從佇列中刪除元素稱為出隊,其後繼元素就成為新的隊頭元素。

  • 特點: 先進先出(FIFO)
  • 儲存結構: 可用順序表和連結串列來儲存佇列,分別為順序隊、鏈隊

01. 順序佇列

假溢位問題:

  1. 隊尾指標rear -> 剛進隊元素位置
  2. 隊首指標fort -> 剛出隊元素位置
  3. 進隊時 rear 向後移動
  4. 出隊時 fort 向後移動

這樣進過一系列的出隊和進隊操作之後,兩個指標最終會到達陣列末端,maxsize-1處,隊中沒有元素,但仍然無法進隊,這就是“假溢位問題”

解決辦法:

將陣列組成一個環,讓rear和fort沿著環走,這樣就產生了迴圈佇列,可以通過執行語句 fort = (fort +1)%maxsize 實現環形道路走。

隊滿:

(rear+1)%maxsize == fort   :  (qu.rear+1)%maxsize == qu.fort

隊空:

fort == rear

元素x進隊(移動隊尾指標):元素入隊時,先移動指標,後存入元素

qu.rear = (qu.rear + 1)%maxsize;
qu.data[qu.rear] = x;

元素x出隊(移動隊首指標):元素出隊時,先移動指標,再取出元素

qu.fort = (qu.fort +1)%maxsize;
x = qu.data[qu.fort];

1) 初始化佇列

void  initQueue(SqQueue  &qu)
{
	qu.fort = qu.rear = 0;
}

2) 判斷隊空

init  isQueueEmpty(SqQueue  qu)
{
	if(qu.fort  ==  qu.rear)
		return  1;
	else
		return  0;
}

3) 進隊演算法

init  enQueue(SqQueue  &qu , int x)
{
	if((qu.rear+1)%maxsize == qu.fort)
		return  0;

	qu.rear = (qu.rar+1)%maxsize;
	qu.data[qu.rear] = x;
	return  1;
}

4) 出隊演算法

int  deQueue(SqQueue  &qu , int &x)
{
	if(qu.fort == qu.rear)
		return  0;
	qu.fort = (qu.fornt+1)%maxsize;
	x = qu.data[qu.fornt];
	return  1;
}

02. 鏈隊

鏈隊就是採用鏈式儲存結構儲存佇列(這裡採用單鏈表實現)

  • 特點:不存在佇列滿上溢的情況 隊空狀態:lqu ->rear == NULL 或 lqu -> fort == NULL 隊空狀態:不存在這種情況 元素進隊操作:(假設p指向進隊元素)
lqu->rear->next  =  p; 
lqu->rear  =  p;

元素出隊操作:(假設x儲存出隊元素)

p  =  lqu->fort;
lqu->fort = p->next;
x = p->data;
free(p);

1) 鏈隊型別定義

typedef  struct
{
	QNode  *fornt;
	QNode  *rear;
}LiQueue;

2) 初始化鏈隊

void  initQueue(LiQueue  *&lqu)
{
	lqu = (LiQueue *)malloc(sizeof(LiQueue));
	lqu->fornt  =  lqu->rear  =  NULL;
}

3) 判斷隊空

int  isQueueEmpty(LiQueue  *lqu)
{
	if(lqu->rear  ==  NULL  ||  lqu->fort  ==  NULL)
		return  1;
	else
		return  0;
}

4) 入隊演算法

void  enQueue(LiQueue  *lqu , int  x)
{
	QNode  *p;
	p  =   (QNode *)malloc(sizeof(QNode));
	p->data  =  x;
	p->next  NULL;
	if(lqu-rear  ==  NULL)
		lqu->fornt  =  lqu->rear  =  p;
	else
	{
	lqu->rear->next  =  p;
	lqu->rear  =  p;
}
}

5) 出隊演算法

int  deQueue(LiQueue  *lqu , int  &x)
{
	QNode  *p;
	if(lqu->rear  ==  NULL)
		return  0;
	else
		p  =  lqu->fornt;
	if(lqu->fornt  ==  lqu->rear)
		lqu->fornt  =  lqu->rear  =  NULL;
	else
		lqu->fornt  =  lqu->fornt->next;
	x  =  p->data;
	free(p)
	return  1}