《演算法導論》第十章——基本資料結構(一):棧與佇列
引言:演算法操作的集合可以隨著時間的改變而增大,減小,或者產生其他變化,我們稱這種集合是動態的。接下來的五章,我們將研究計算機上表示和操作有窮動態集合的一些基本技術。本文主要為你講解棧與佇列的操作和實現,建議將這些操作製作成庫,方便以後的引用,避免重複編碼。系列文章為演算法導論的筆記和相關習題解答。
本文來源:棧與佇列
動態集合的元素
元素包括兩個部分:關鍵字+衛星資料
動態集合上的操作
主要包括兩個大的方面:查詢
我們約定:集合為S,關鍵字為k,指向元素的指標為x
Search(S,k)
Inserrt(S,x)
Delete(S,x)
Minimum(S)
Maximum( S )
Successor (S,x)
Predecessor(S,x)
棧和佇列
一、棧
實現了一種先進先出的策略。通常情況下我們採用陣列加棧頂指示top來實現,約定top==0(或者-1)的時候表示棧為空;同時如果stack的長度是m,那麼要考慮元素個數超過m以後產生的溢位問題。棧的一些定義和基本操作如下:
#ifndef MAXSTACKSIZE
#define MAXSTACKSIZE 200
#endif
typedef int StackDataType;
typedef struct mystack{
int top;
StackDataType data[MAXSTACKSIZE];
}Stack,*StackPointer;
extern int IsEmpty(Stack s);
extern int Push(StackPointer s, StackDataType element);
extern StackDataType Pop(StackPointer s);
註明:stack的資料結構還可以定義一個指標和大小,來取代陣列。這些操作的實現方式如下:
#include"stack.h"
#include<stdlib.h>
#include<stdio.h>
StackDataType Pop(StackPointer s){
if(s->top==-1){
printf("the stack is already empty!\n");
exit(1);
}
--(s->top);
return s->data[s->top+1];
}
int IsEmpty(Stack s){
if(s.top==-1){
return 1;
}
else{
return 0;
}
}
int Push(StackPointer s,StackDataType element){
if(s->top >= MAXSTACKSIZE-1){
printf("the stack is over flow!\n");
return 0;
}
++(s->top);
s->data[s->top]=element;
return 1;
}
二、佇列
我們可以把佇列想象成排隊等待服務的人群,同樣也可以用 陣列+對頭指標+對尾指標 來實現佇列這個資料結構;其中,head表示下一個要出列的元素,tail表示剛剛進入佇列的元素。另外,為了實現環繞,我們需要把佇列實現成為迴圈陣列的模式,這個可以通過取模運算來實現。這樣,head==tail+1表示佇列已經滿了;但是,此時我們會發現,如果我們讓元素逐個出列,那麼當最後一個元素出列的時候,同樣滿足head=tail+1;也就是說,佇列在空和滿的情況下具有相同的抽象條件。為了對此進行區分,我們用tail表示下一個進入佇列的元素將要進入佇列的位置,那麼,初始化情況下,所以head=tail表示佇列為空,初始情況下,head=tail=0;如果我們用head=tail+1表示佇列為滿的情況,意味著這個情況下,佇列中有一個位置處於沒有利用的狀態,如果要利用這個元素,又會出現head=tail表示空和滿兩種情況。
關於佇列的一些操作例項可以看下圖,從而理解上面一段中的相關情況:
佇列的一些定義的基本的操作如下:
#ifndef MAXQUEUESIZE
#define MAXQUEUESIZE 200
#endif
typedef int QueueDataType;
typedef struct myqueue{
int tail;
int head;
QueueDataType data[MAXQUEUESIZE];
}Queue,*QueuePointer;
extern int IsEmpty(Queue queue);
extern int IsFull(Queue queue);
extern int EnQueue(QueuePointer queuep, QueueDataType element);
extern QueueDataType DeQueue(QueuePointer queuep);
操作實現:
#include"queue.h"
#include<stdlib.h>
#include<stdio.h>
/*make sure the queue is not empty when you delete element from it*/
QueueDataType DeQueue(QueuePointer queue){
if(queue->head==queue->tail){
printf("the queue is already empty!\n");
exit(1);
}
QueueDataType temp;
temp=queue->data[queue->head];
++(queue->head);
if(queue->head==MAXQUEUESIZE)//
queue->head=0;
return temp;
}
int IsEmpty(Queue queue){
if(queue.head==queue.tail){
return 1;
}
else{
return 0;
}
}
int IsFull(Queue queue){
if(queue.head==(queue.tail+1)%MAXQUEUESIZE){
return 1;
}
else
return 0;
}
int EnQueue(QueuePointer queue,QueueDataType element){
if(IsFull((*queue))){
printf("the queue is over flow!\n");
return 0;
}
queue->data[queue->tail]=element;
++(queue->tail);
if(queue->tail==MAXQUEUESIZE)
queue->tail=0;
return 1;
}
心得:棧與佇列,分別是兩種FIFO和FILO的資料結構,至於具體實現,棧的增長和佇列進出的方向完全可以由使用者定義。另外,在實際的程式設計中,以迴圈佇列的實現為例,容易出現邏輯錯誤的地方在於條件判斷和邊界條件的設定。其中條件判斷要是充要條件,也就是說,你的程式碼需要能準確反應你的文字表述的意圖,雖然我們設定的條件是佇列滿,但是如果用head=tail,雖然表示了佇列滿的情況,但是它也表示佇列是空的情況,所以是不正確的。比如判斷佇列是滿還是空,如果我們想要將陣列的每個元素都利用,這時就會發現佇列在滿和空的時候滿足同樣的條件head=tail,顯然,這是應該避免的;所以浪費了一個空間,來區分佇列是滿還是空這個情況。經驗:行動前周密的思考能大量節省時間。
練習:程式設計實現2,4,5,6,7:
2,一個棧stack1從低地址到高地址,另外一個棧stack2從高地址到低地址:當top1>=top2時,棧溢位。
4,解答:參見本文中的程式碼,裡面有對溢位情況的處理
5,解答:參見程式碼biqueue.c
6,解答:兩個棧,棧底相連就是一個佇列,但是要注意這兩個棧為空的邊界條件。
7,解答:兩個佇列,參考下圖
相關文章
- 資料結構與演算法-棧與佇列資料結構演算法佇列
- 演算法導論_第十章_基本資料結構演算法資料結構
- 資料結構-棧與佇列資料結構佇列
- 資料結構:棧與佇列資料結構佇列
- 資料結構與演算法(三),棧與佇列資料結構演算法佇列
- JavaScript的資料結構與演算法(一)——棧和佇列JavaScript資料結構演算法佇列
- python資料結構與演算法——棧、佇列與雙端佇列Python資料結構演算法佇列
- 《資料結構與演算法》——表、棧和佇列資料結構演算法佇列
- 資料結構與演算法(二)佇列、棧、連結串列資料結構演算法佇列
- 資料結構—棧/佇列資料結構佇列
- 資料結構-佇列、棧資料結構佇列
- php實現基本資料結構之棧、佇列PHP資料結構佇列
- 三、資料結構演算法-棧、佇列、優先佇列、雙端佇列資料結構演算法佇列
- 資料結構—棧和佇列資料結構佇列
- 資料結構(棧和佇列)資料結構佇列
- 【資料結構】--棧和佇列資料結構佇列
- 結構與演算法(02):佇列和棧結構演算法佇列
- 資料結構與演算法-佇列資料結構演算法佇列
- 資料結構與演算法——佇列(環形佇列)資料結構演算法佇列
- 資料結構之棧和佇列資料結構佇列
- JavaScript資料結構之陣列棧佇列JavaScript資料結構陣列佇列
- 學習JavaScript資料結構(一)——棧和佇列JavaScript資料結構佇列
- Python資料結構與演算法系列四:棧和佇列Python資料結構演算法佇列
- C#資料結構與演算法2-C# 棧和佇列C#資料結構演算法佇列
- uva 11995 棧,佇列,優先佇列,等基本資料結構的應用與理解佇列資料結構
- 資料結構與演算法分析——佇列資料結構演算法佇列
- javascript資料結構與演算法-佇列JavaScript資料結構演算法佇列
- javascript資料結構與演算法---佇列JavaScript資料結構演算法佇列
- 資料結構與演算法分析 讀書筆記(連結串列 棧 佇列)資料結構演算法筆記佇列
- 線性結構 佇列與棧佇列
- 【資料結構】棧(Stack)和佇列(Queue)資料結構佇列
- 資料結構二之棧和佇列資料結構佇列
- 【資料結構】回顧表、棧、佇列資料結構佇列
- 淺談演算法和資料結構(1):棧和佇列演算法資料結構佇列
- 資料結構與演算法JavaScript (二) :佇列資料結構演算法JavaScript佇列
- 資料結構與演算法—稀疏陣列和佇列資料結構演算法陣列佇列
- 資料結構-js實現棧和佇列資料結構JS佇列
- IT名企演算法與資料結構題目最優解--棧和佇列演算法資料結構佇列