1 / 22

資料結構與演算法

資料結構與演算法. 課程教學投影片. 第八章 – 佇列. 本章各段大綱 8-1 佇列概觀 8-2 佇列的資料結構和操作 8-3 環狀佇列 8-4 雙向佇列和特殊佇列. 8-1 佇列概觀-定義. 「佇列」( Queue) 抽象的邏輯結構 將物件排列成隊伍,有入口和出口 物件只能從入口進入,只能從出口出去 不能從中間插隊 定義 佇列是一個有序串列( ordered list) 所有加入的動作只能在一個特定的入口進行 刪除的動作只能在一個特定的出口進行. 8-1 佇列概觀-特性. 先進先出 first in first out ( FIFO) 後進後出

laken
Download Presentation

資料結構與演算法

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 資料結構與演算法 課程教學投影片

  2. 第八章–佇列 • 本章各段大綱 • 8-1 佇列概觀 • 8-2 佇列的資料結構和操作 • 8-3 環狀佇列 • 8-4 雙向佇列和特殊佇列

  3. 8-1 佇列概觀-定義 • 「佇列」(Queue) • 抽象的邏輯結構 • 將物件排列成隊伍,有入口和出口 • 物件只能從入口進入,只能從出口出去 • 不能從中間插隊 • 定義 • 佇列是一個有序串列(ordered list) • 所有加入的動作只能在一個特定的入口進行 • 刪除的動作只能在一個特定的出口進行

  4. 8-1 佇列概觀-特性 • 先進先出 • first in first out (FIFO) • 後進後出 • last in last out ( LILO) • 加入元素到佇列中稱為加入(Addition) • 自佇列中刪除元素稱為刪除(Delete)

  5. 8-1 佇列概觀-範例 (1) 放入A (2) 放入B (3) 取出A (4) 放入C (5) 取出B (6)取出C (2) (1) 放入 (4) C B A (3) 取出A (5) 取出B (6) 取出C 放入ABC  輸出ABC,次序未變

  6. 8-1 佇列概觀-定義 定義 • 如果Q={ai,ai+1,..., aj-1,aj}為一佇列,則稱ai為前端(front)元素,aj為後端(rear)元素,i為前端(front),j為後端(rear),增加資料時由後端加入,刪除資料時由前端刪除,rear-front+1為佇列長度(length) 即在佇列中的元素個數 i 前端 j 後端

  7. 8-1 佇列概觀-運用 • 列印佇列 • 因列印工作較緩慢,以佇列方式安排列印工作,使系統可以對使用者的其他需求作即時處理 • CPU分時(time sharing)作業 • CPU以排序方式,將處理的工作置於佇列中,以分時的方式輪流處理佇列中的工作 • 鍵盤緩衝區的應用 • 輸入鍵盤資料時,系統未能即時反應輸入動作時,以鍵盤緩衝區作為佇列暫存資料

  8. 8-2 佇列的資料結構和操作 define maxq 100; char queue[maxq]; int front =-1; int rear =-1; real=2 real=0 real=1 real=0

  9. 8-2 佇列的資料結構和操作 maxtop-1 1 • 判斷佇列是否已滿     if (rear==maxtop-1)      … /*佇列已滿*/     else      … /*佇列未滿*/     end if • 判斷佇列是否為空     if (rear==front)      … /*佇列為空*/     else      … /*佇列不為空*/     end if front rear

  10. 8-2 佇列的資料結構和操作 • 將資料放入佇列 void addq(int data) { if (isfull())queuefull()/*isfull()檢查是否queue已滿*/     else queue[++rear]=data /*queuefull()是作相關處理*/ } /*rear先加1, 再當成queue的指標放入data 未放入的區域 已刪除的區域 作用中的區域 a.原先的位置 maxq-1 front=i rear=n 未放入的區域 已刪除的區域 作用中的區域 b.加入資料 (addq) maxq-1 front=i 不變 rear=n+1

  11. 8-2 佇列的資料結構和操作 • 將資料從佇列取出 int delq() {     if (isempty()) /*isempty是檢查佇列是否已空了*/ {    queueempty(); /*queueempty是佇列空時,又要取出資料的處理*/ return 0; /*傳回0代表失敗*/ }else return queue[++front]; /*一切正常front,加1,且傳回資料*/ } 未放入的區域 已刪除的區域 作用中的區域 a.原先狀態 maxq-1 front=i rear=n (課本誤植為n+1) 未放入的區域 已刪除的區域 作用中的區域 b.刪除資料 (delq) maxq-1 rear=n ++front => front=i+1

  12. 8-2 佇列的資料結構和操作 • 佇列已滿否? • 在addq()演算法中, rear只會往後增加,最多至max-1 int isfull() {     if (real==max-1) return 1; /* 1代表已滿 */   else return 0;  /* 0代表未滿 */ } 作用中的區域 未放入的區域 已刪除的區域 a.原先狀態 maxq-1 front=i rear 已刪除的區域 作用中的區域 b.增加資料 (delq) rear=maxq-1 front=i

  13. 8-2 佇列的資料結構和操作 • 佇列已空否? • 檢查佇列是否已空時, front 一直往rear逼近,且rear==front時代表佇列已經空了 int isempty() {     if (front==real) return 1; /* 1代表已空了 */   else return 0;  /* 0代表未空 */ } 作用中的區域 未放入的區域 已刪除的區域 a.原先狀態 maxq-1 front=i rear=i+1 已刪除的區域 b.刪除資料 (delq) front=rear=i+1 c.刪除資料時, real=front, 代表已空了

  14. 8-2 佇列的資料結構和操作 • 範例1 (pp.8-10) • 輸入到佇列的整數資料 • 由佇列輸出的整數資料

  15. 8-3 環狀佇列 • 線性佇列: • 以前端front 紀錄刪除資料及後端rear紀錄新增加資料的位置 • rear到達末端:陣列很快達到佇列已滿的狀態,但front之前都沒有資料 • 環形陣列: • 重新利用已刪除區域,當rear到達最大值時從前端開始編號放入新資料 • 佇列已滿:所有位置放滿資料

  16. 8-3 環狀佇列 • front 和rear到達maxq-1時,重新設為0開始 • 以C為例,採用%運算子 當rear=maxq-1時 (rear+1)%maxq0

  17. 2 3 1 4 0 5 (2)加入d3, front=2, rear=5 (1)目前狀態front=2, rear=4 (3)刪除d1, front=3, rear=5 (4)加入d4, front=3, rear=0 2 3 2 3 2 3 2 3 1 4 1 4 1 4 1 4 d1 d1 0 0 0 0 5 5 5 5 d2 d2 d2 d2 d3 d3 d4 d3 8-3 環狀佇列 問題 //當front==rear時無法 //知道是否為空的或已滿 環狀佇列宣告 define maxq 6 int queue[maxq]; int front=-1; // 此初始設定會導致無法判斷已滿的狀況 int rear=-1; (rear+1)%6 =(4+1)%6 =5 (front+1)%6 =(2+1)%6 =3 (rear+1)%6 =(5+1)%6 =0 此時rear從0開始,同理front到達5時,也會從0開始

  18. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 /* 演算法名稱:addcq & delcq */ /* 輸入: */ /* 輸出: */ defint cmaxq 100; char cqueue[cmaxq]; int cfront=-1; int crear=-1; void addcq (int data) { if (iscfull()) cqueuefull() else cqueue [++rear%cmaxq]=data } int delcq() { if (iscempty()) { cqueueempty(); return 0; } else return cqueue[++cfront%cmaxq]; } 8-3 環狀佇列-演算法

  19. 01 02 03 04 05 06 07 08 09 01 02 03 04 05 06 07 08 09 10 /* 演算法名稱:iscEmpty*/ /* 輸入: */ /* 輸出: */ int iscEmpty() { if (rear==ftont) return 1; /*1代表佇列已空*/ else return 0; /*0代表佇列未空*/ } /* 演算法名稱:iscfull*/ /* 輸入: */ /* 輸出: */ int iscfull() { if ((rear+1)%maxq = ftont) return 1; /*1代表佇列已滿*/ else return 0; /*0代表佇列未滿*/ } 8-3 環狀佇列-演算法 /*請參考前面範本說明,並非如此 在((rear+1)%maxq = ftont條件下 仍有一個空位

  20. 8-3 環狀佇列-演算法 • 課本範例程式所遭遇問題 • 並未發揮偵測佇列已滿或已空的功能 • front及rear的初始設定不適合環狀序列 • 資料取出的動作並未將資料從佇列中刪除 • 請改寫課本程式使其環狀佇列可以發揮功能

  21. 8-4 雙向佇列和特殊佇列 • 特殊佇列 • 重點在於改變先前介紹的addq()或addcq演算法 • 例如,假如將佇列結構應用在醫院診所的掛號系統,如果求診者一視同仁,都按照掛號編號看診,則當有需要急診之某一病患,或者有優先權較高者可以把要處理的先放到佇列的最前面,這樣在從佇列取出時就可以最先取出了

  22. 8-4 雙向佇列和特殊佇列 • 雙向佇列 • 線性佇列和環狀佇列只能有唯一的入口和唯一的出口,此稱為單向佇列(single-end-queue),佇列可加以變化成為兩端都可入口和出口的雙向佇列(double-end-queue,dqueue)。 • 雙向佇列是擴充原先前端front只能刪除資料,後端rear只能增加資料的功能,讓前端front可能加入資料,後端rear也能刪除資料,因此可改為左端(left)和右端(right)。Left或right要加入資料或刪除資料是由你設計的程式來控制。

More Related