逢 甲 大 學
資 訊 工 程 學 系 專 題 報 告
網路教學系統
– 堆疊與佇列
劉 志 祥 (四丙)
學
生: 楊 立 宇 (四丙)
周 啟 文 (四丙)
指
導
教
授 : 黃 溪 春
中華民國九十一年十一月
目 錄
圖目錄 ………Ⅳ 表目錄 ………ˇ 程式目錄 ………Ⅵ 摘要 ………Ⅶ 第一章 導論 1-1 製作動機 ………1 1-2 系統簡介 ………1 1-3 工作分配 ………2 第二章 使用工具簡介 2-1 Flash MX ………5 2-2 PhotoImpact ………7 2-3 PHP ………9 2-4 JAVASCRIPT ………11 2-5 MYSQL ………12 2-6 Apache HTTP Server ………13 2-7 Frontpage ………16 第三章 教學內容概要 3-1 堆疊(Stack) ………17 3-2 堆疊的教學與程式實作解說 ………18 3-2-1 一般靜態的實作 ………18 3-2-2 以動態鏈結串列實作 ………21 3-3 佇列(Queue) ………24 3-4 佇列的教學與程式實作解說 ………25 3-4-1 一般靜態的實作 ………25 3-4-2 以動態鏈結串列實作 ………29 3-5 環狀佇列(Circular Queue) ………32 3-6 環狀佇列的教學與程式實作解說 ………33 3-6-1 一般靜態的實作 ………33 3-6-2 以動態鏈結串列實作 ………37 3-7 生活實例說明 ………41 3-8 應用:以單一陣列實作一個堆疊及一個佇列 ……43 3-8-1 原理解說部分 ………433-8-2 程式解說部分 ………46 3-8-3 結論 ………48 第四章 系統分析及設計 4-1 主要教學內容 ………50 4-1-1 堆疊教學內容場景設計 ………52 4-1-2 佇列教學內容場景設計 ………53 4-1-3 題庫測驗規畫 ………55 4-1-4 討論區 ………59 4-2 訪客子系統 ………59 4-3 註冊認證子系統 ………60 4-4 管理者子系統 ………62 4-5 資料庫設計 ………64 4-5-1 使用者資料表設計 ………64 4-5-2 題庫資料表設計 ………69 4-5-3
資料庫實體關係圖 ………71 第五章 系統實作 5-1 教學子系統 ………72 5-1-1 教學內容的實作 ………72 5-1-2 生活實例 ………77 5-1-3 題庫測驗 ………77 5-1-4 討論區架設 ………77 5-2 訪客子系統 ………78 5-3 註冊認證子系統 ………78 5-4 管理者子系統 ………79 5-4-1 管理系統使用說明 ………79 5-4-2 列出所有使用者資料 ………79 5-4-3 查詢使用者資料 ………79 5-4-4 更新使用者資料 ………80 5-4-5 刪除使用者資料 ………80 5-4-6 查詢使用者學習成果 ………80 第六章 疑難排解 6-1 主要教學內容 ………81 6-2 註冊認證子系統 ………82 6-3 管理者子系統 ………82
第七章 總結
7-1 系統優點與缺點 ………83
7-2 專題製作之心得 ………84
參考資料 ………86
圖目錄
圖 1-1 工作進度甘特圖 ………4
圖 2-1 PHP 在 Client-Server 架構中所拌演的角色 ………9
圖 2-2 以 Apache 為基礎的 Web Server 架構 ………14
圖 3-1 Stack 資料結構示意圖 ………17 圖 3-2 動態鏈結堆疊之結構示意圖 ………22 圖 3-3 佇列結構示意圖 ………25 圖 3-4 靜態佇列之結構示意圖 ………26 圖 3-5 動態鏈結佇列示意圖 ………29 圖 3-6 環狀佇列示意圖 ………33 圖 3-7 環狀鏈結佇列之結構示意圖 ………37 圖 3-8 堆疊生活實例示意圖 ………41 圖 3-9 佇列生活實例示意圖 ………42 圖 3-10 應用實作的基本架構圖 ………43 圖 3-11 堆疊借用空間後的說明圖(1)………44 圖 3-12 堆疊借用空間後的說明圖(2)………44 圖 3-13 佇列借用空間前的說明圖(1)………45 圖 3-14 佇列借用空間前的說明圖(2)………46 圖 4-1 主系統架構圖 ………49 圖 4-2 教學子系統架構圖 ………50 圖 4-3 進入教學之架構圖 ………51 圖 4-4 堆疊教學頁的架構圖 ………52 圖 4-5 堆疊教學頁面的互動式操作 ………53 圖 4-6 佇列教學頁面的互動式操作 ………54 圖 4-7 佇列教學頁的架構圖 ………55 圖 4-8 題庫測驗流程圖 ………58 圖 4-9 訪客子系統架構圖 ………59 圖 4-10 註冊認證子系統流程圖 ………61 圖 4-11 管理者子系統流程圖 ………63 圖 4-12 資料庫的正規化 ………66 圖 4-13 資料庫實體關係圖 ………71 圖 5-1 Flash MX 操作介面 ………72 圖 5-2 圖層 & 物件 & 關鍵影格 ………73 圖 5-3 建立新元件 ………74 圖 5-4 元件編輯 ………74 圖 5-5(a) 一般(UP) ………75
圖 5-5(b) 滑鼠經過(OVER) ………75 圖 5-5(c) 按下(DOWN) ………75 圖 5-5(d) 反應區(HIT) ………75 圖 5-6(a) 尚未按下按鈕的狀態 ………75 圖 5-6(b) 按下按鈕的狀態 ………75 圖 5-7 ActionScript 視窗 ………76 圖 5-8 程式說明 ………76 圖 A-1 系統登入頁 ………89 圖 A-2 註冊頁面 ………90 圖 A-3 系統選擇頁面 ………90 圖 A-4 教學子系統主選單(Flash 動畫) ………91 圖 A-5 教學內容選單(Flash 動畫) …… ………91 圖 A-6 教學內容頁面 ………92 圖 A-7 管理者子系統操作畫面 ………… ………93 圖 A-8 使用者資料更新頁面 ……… ………93
表目錄
表 1-1 工作進度表 ………3 表 2-1 點陣圖和向量圖的優缺點比較 ………5 表 2-2 各種 Server 端程式語言的優缺點比較 ………10 表 2-3 各種 Web Server 軟體效能測試評比 ………14 表 4-1 成績與累績分數分配表 ………57程式目錄
程式 3-1 靜態堆疊的陣列(Array)結構定義程式 ………19 程式 3-2 靜態堆疊的加入動作(Push)程式 ………20 程式 3-3 堆疊的容量滿載程式 ………20 程式 3-4 靜態堆疊的取出動作(Pop)程式 ………21 程式 3-5 堆疊的資料為空之程式 ………21 程式 3-6 動態堆疊的鏈結串列(Linked-list)結構定義程式 ……22 程式 3-7 動態堆疊的加入動作(Push)程式 ………23 程式 3-8 動態堆疊的取出動作(Pop)程式 ………24 程式 3-9 靜態佇列的陣列(Array)結構定義程式 ………26 程式 3-10 靜態佇列的加入動作(Addq)程式 ………27 程式 3-11 靜態佇列的刪除動作(Deleteq)程式 ………28 程式 3-12 動態佇列的鏈結串列(Linked-list)結構定義程式……30 程式 3-13 動態佇列的加入動作(Addq)程式 ………31 程式 3-14 動態佇列的刪除動作(Deleteq)程式 ………32 程式 3-15 靜態環狀佇列的陣列(Array)結構定義程式 …………34 程式 3-16 靜態環狀佇列的加入動作(Addq)程式 ………35 程式 3-17 靜態環狀佇列的刪除動作(Deleteq)程式 …………36 程式 3-18 動態環狀佇列的鏈結串列 (Linked-list)結構定義程式 ………37 程式 3-19 動態環狀佇列的加入動作(Addq)程式 ………39 程式 3-20 動態環狀佇列的刪除動作(Deleteq)程式 …………40 程式 3-21 應用範例程式解說 ………48摘要
傳統的電腦輔助教學,隨著網路環境蓬勃發展的今天,已經漸漸 地轉向網路超媒體化的環境發展,成為網路教學系統。電腦輔助教學 與網路環境整合而成的網路教學系統,為使用者帶來了許多的好處; 網路教學系統的使用者,可以和各個分散在世界上不同地區的使用者 共同學習,相互研討,因而不會被侷限在封閉的教學環境中。而且, 網路教學系統也保留了傳統電腦輔助教學的特色及優點,藉由動態的 教學內容,與使用者進行互動教學,增加了使用者的學習參與感。 教師以及管理者則可以藉由網路開放式的環境,修改以及新增教 材內容,使得教學內容變得更有彈性。並且,透過資料庫的支援,儲 存使用者的學習資訊,更可以讓教師以及管理者對個別使用者的學習 成效做出評估,以作為教學內容深度調整的依據。 本系統包含教學子系統、訪客子系統、註冊認證子系統,管理者 子系統。使用者在一開始使用系統的時候,透過註冊認證子系統,在 資料庫中留下個人資料,並建立學習相關資訊,包含系統使用次數、 系統使用總時數、測驗成績等資訊。完成註冊的使用者,可以使用完 整的教學子系統功能。教學子系統的主題為資料結構中的堆疊與佇 列。透過互動性的教學內容、生活實例解說、題庫測驗、討論區、以 及參考資料等內容,使用者可以藉由這些系統功能,在生動的學習環 境中,達到良好的學習成效。第一章 導論
1-1 製作動機 資料結構,在資訊相關領域的課程中,一直是相當重要的基礎課 題。雖然,市面上出版有關資料結構的書籍種類繁多。但是,我們認 為,資料結構最佳的學習方式,除了書本上的知識以外,還要加上與 學習者的互動,提高學習者的參與感。所以我們透過動畫的製作,以 實驗性質的方式,製作了堆疊與佇列的資料結構教學。除此之外,我 們還有一個額外的目的;那就是,提供教師一個能夠觀察學生學習歷 程記錄的環境,並且藉由學生的測驗成績來評估學生的學習效率。以 方便於對教學內容做擴充與改良。 1-2 系統簡介 我們的教學系統是由四個子系統所組成,包括: 1. 教學子系統: 包含主要的堆疊與佇列教學內容,僅提供服務給註冊使用 者。以 Flash 動畫以及 JavaScript 特效,透過動態的文件說 明,強調互動式學習的環境,呈現教學內容給使用者。其他教 學部份主要還包含生活實例、題庫測驗、討論板等功能。 2. 註冊認證子系統: 提供使用者註冊介面,以便將使用者的資料登錄到資料庫 中。並且進行使用者身分認證的工作。系統會自動判斷使用者的權限,以決定開放給使用者使用的子系統範圍。 3. 管理者子系統: 僅提供給具有管理者權限的使用者使用。能進行學員的資 料管理,追蹤學員的學習歷程,並且提供管理者以及教師評 估使用者學習效率的參考資料。 4. 訪客子系統: 提供訪客等非註冊使用者參觀用,以及統系功能介紹。不 能使用大部份的教學資源。 1-3 工作分配 學生製作專題實驗的好處,除了可以訓練系統分析、設計和實作 的能力之外,還可以透過團隊工作的機制,讓學生學習分工合作的精 神,以適應未來職場上的工作模式及需求。因此,在系統開發的過程 中,工作的規畫與人力的分配,也是一件相當重要的工作。 我們的系統一共由 3 位組員來開發。系統內部主要的工作分為十 四大項。
表 1-1 是每位組員所負責的工作。 表 1-1 工作分配表 劉志祥 楊立宇 周啟文 資料收集 ˇ ˇ ˇ 系統分析 ˇ ˇ ˇ 系統設計 ˇ ˇ ˇ 資料庫建置 ˇ 註冊及登入系統程 式編寫 ˇ 管理系統程式編寫 ˇ 堆疊教學內容及動 畫製作 ˇ 佇列教學內容及動 畫製作 ˇ 題庫測驗製作 ˇ ˇ ˇ 討論板架設 ˇ 系統整合 ˇ 介面美化工作 ˇ ˇ ˇ 系統測試 ˇ ˇ ˇ 書面報告 ˇ ˇ ˇ
為了在規定的時間內完成工作,我們規畫出了工作進度甘特圖, 如圖 1-1 所示。
第二章 使用工具簡介
2-1 Flash MX Flash 是由美國 Macromedia 公司所研發出來的軟體,由於它的 問世,為網頁設計者提供了另一種製作動態網頁的新選擇,它結合了 音效、影像、動畫,具備了高品質、體積小、互動性高的優點,它的 特色大概分成下列幾點: (1)向量式繪圖: Flash 是利用向量式的繪圖方式,而不是一般點陣式的繪圖 方式,表 2-1 為這兩種繪圖方式的差別與優缺點的比較: 表 2-1 點陣圖和向量圖的優缺點比較 點 陣 圖 向 量 圖 外觀 放大後出現鋸尺 放大後仍不失真 原理 圖檔儲存每塊像素的 色彩資料,從網路觀 看時,必需下載完每 一個素,才能在瀏灠 者的電腦呈現 圖檔儲存錨點間曲線及 色彩的公式,觀看時再由 瀏灠者的電腦將公式轉 成色塊。錨點:在圖塊的 邊緣,通常在轉折處,數 量很少 優點 再複雜的色彩資料也 可逐點記錄,適合處 理變化豐富的圖案 公式代替圖像,檔案極 小,網路下載較快,任 意變形也不失真缺點 大量像素資料,檔案 較大,網路下載較 慢,任意變形後易失 真 公式不夠成熟,無法記 錄複雜的色彩資料,適 合處理變化較少的圖案 (2)影音整合: Flash 可以匯入各種聲音檔 (wav) (mp3),為整個動畫加上 背景音樂及特殊音效,為因應網路傳輸下載的需要,Flash 更可壓縮音效輸出電影,使檔案的體積變小。 (3)多種互動性的指令: Flash 不用寫複雜的程式語言,可以用 Actions 中的各種 互動性指令來設定、編輯動畫。 (4)動畫檔案體積小:
網頁常用的 GIF 動畫,是利用 Frame By Frame (續格)的 原理,即一影格放置一張圖,一段小小的動畫可能就需要多 張相同大小的圖組合而成。而 Flash 是利用 Tweening 的 原理,模擬出物件移動變形的動畫,不需要像 GIF 一樣要 放置很多張圖,因此同樣內容的 Flash 動畫檔和 GIF 動畫 檔比較起來,前者檔案體積小很多,而且 Flash 的動畫還 可以匯入音效,加入 Action 的互動,比起 GIF 動畫,效果 更炫。 (5)可模擬網頁動畫下載的情況: Flash 提供動畫的網路測試環境,讓使用者可以模擬網路上 動畫的下載播放情形,可得知電影檔案是否過大,來作為修 改及是否要加入下載等待畫面的參考指標。 綜合以上的 Flash 的特色,証明了 Flash 在製作動畫方面功能的 強大與實用性,這也就是為什麼我們要採用 Flash 來製作動畫的 原因。
2-2 PhotoImpact PhotoImpact 是一個令人容易學習與熟悉的軟體,初用時會感覺 其各種功能皆能簡易上手,且介面相當明顯完整,它是提供以物件式 圖層給使用者編輯,唯其圖層和遮罩的功能較不齊全,未有妥善處理 圖層間上下層遮罩的問題,算是一個適合初階至中階的影像處理軟 體。其全方位的視野,當然還是比不上 Photoshop 的操作介面,也沒 有 Photoshop 操作功能複雜度高;相較於 Painter,PhotoImpact 則 有較多的圖形美化處理,也不比 Painter 單調。
PhotoImpact 與 Photoshop 和 Painter 比較的特點如下:
1. Photoshop 物件的選取較 PhotoImpact 靈敏,Painter 則較為遲鈍 的。
2. Photoshop 與 PhotoImpact 文字的選用也較靈敏,而 Painter 的 文字使用介面則較簡陋。
3. Photoshop 與 PhotoImpact 畫刷的分類較清楚,且易用;Painter 則少且簡易。
4. Photoshop Screen Capture 可用以擷取畫面,Painter 亦可用 Print Screen 鍵植入擷取畫面,但動態影像無法擷取,如影片檔 之類(mpeg、dat、avi、…)。
5. Photoshop 與 PhotoImpact 畫刷模式可以產生新圖層,Painter 則 無。 6. 文字的特效 Photoshop 與 PhotoImpact 皆有,但前者較後者專業 且變化多,Painter 則無特效。 7. 工具皆在工具列清楚顯示,但前二者較繁多。 因此我們選用 PhotoImpact 此較中階的軟體來作初步的圖形設計跟 一般的文字特效,與用來作圖片的美化,提供其他軟體美化的圖形使 用配合。
2-3 PHP
PHP (Hypertext Preprocessor) 是一種 Open Source 的 Server 端 HTML 嵌入式 Script 語言。它是由 Rasmus Lerdorf 這位軟體工程 師所開發的 Personal Home Page Tools 所演進而來的。PHP 可以完 成任何 CGI 程式所能做的工作,例如收集並處理 HTML form 表單的資 料、產生動態的網頁內容和處理瀏覽器的 Cookie…等,並且它具有 功能十分強大的應用程式設計介面(API)。特別是對於 Server 端的資 料庫存取,不論是市面上主流或是非主流的資料庫系統,它都有非常 完整的支援度和資料庫存取函數介面。 在 Client-Server 的架構中,PHP 所扮演的角色如圖 2-1 所示。 PHP 核心接受由 Client 端機器發出的 HTTP 請求,到 Server 端的檔 案系統中讀取 test.php 程式檔,然後再把執行完後所輸出的 HTML 網 頁回傳到 Client 端的瀏覽器顯示。因此 Client 端的使用者看到的是 test.php 執行後所輸出的 HTML 呈現的網頁。 圖 2-1 PHP 在 Client-Server 架構中所拌演的角色
我們會選用 PHP 做為我們 Server 端的 Script 語言,主要是因為 PHP 的執行速度非常快。而且,和傳統的 CGI 以及同類型產品 - Microsoft 的 ASP 來比較,它還有許多其他的優點,請參考表 2-2。 表 2-2 各種 Server 端程式語言的優缺點比較 程式界面 ASP CGI 作業平台 均可 Win32 均可
Web Server 支援 數種 IIS 均可
執行效率 快 快 慢 穩定性 佳 中等 最高 開發時間 短 短 中等 使用語言 PHP VB 不限 網頁結合性 佳 佳 差 函數支援度 多 少 不定 系統安全性 佳 極差 最佳 使用網站 多 多 多 改版速度 快 慢 無 PHP 除此之外,它還是免費的,並且完全 Open Source,因此有很多 熱心的開發者為它開發資源。而且,它對 MySQL 資料庫系統的支援度 極佳,因此我們選擇了 PHP 作為我們的 Server 端 Script 語言。
2-4 JavaScript
JavaScript 是由網景(Netscape)公司所研發出來的。相對於 PHP,JavaScript 是一種在 Client 端執行的 HTML 嵌入式 Script 語 言,透過 JavaScript 可以做到回應使用者的需求事件而不用經由網 路來傳輸資料。比方說,當一位使用者經由 form 表單輸入資料時, 它可以不用將資料傳給 Server 端處理後再回傳結果給 Client 端,只 要直接交給 Client 端的應用程式就可以處理了。 雖然 JavaScript 是由網景公司開發出來的,但是由於它在 Client 端處理動態的互動式網頁功能上極為強大,十分受到使用者 的喜愛,所以 Microsoft 公司也在 Internet Explorer 第四版之後開 始支援 JavaScript。JavaScript 的語法和正統的 Java 程式語言十分 類似,以物件為基礎。但它主要應用在動態網頁的處理上,不像 Java 那麼複雜,因此功能沒有 Java 那麼強大。JavaScript 本身也有跨平 台的特性,而且市面上大部份的 Web 瀏覽器都有支援。 在我們的教學系統中,JavaScript 也扮演了重要的角色。透過 它,我們可以增強系統與使用者之間的互動性,加強使用者的學習效 率。雖然藉由 PHP 也可以達到互動網頁的效果,可是因為 PHP 是在 Server 端執行的,因此必須在 Client 端和 Server 端之間傳送資料, 這點造成了很多限制,使得設計上較為困難。而且在網頁特效的應用 上,PHP 的功能也不如 JavaScript。因此,JavaScript 正好可以用 來補 PHP 的不足之處,而且兩者的相容性極高,在實作上比較容易整 合。
2-5 MySQL
MySQL 是一個使用結構化查詢語言(Structured Query Language) 的資料庫系統,它本身是一種 Client-Server 架構的應用程式。大概 在 1981 年的時候, IBM 將 SQL 的標準開放。從那個時候開始,SQL 就在關聯式資料庫(Relational Database)的發展上扮演著極為重要 角色。MySQL 是由 Michael Windenis 使用 C 及 C++語言所寫成的, 符合 ANSI SQL 與 SQL 92 標準。MySQL 最主要的設計目標,是快速以 及強固。MySQL 這套功能強大的資料庫系統,不只具備一般關聯式資 料庫所具備的基本特性,它還具有以下特色: 1. 因為是使用 C 及 C++寫成的,所以移植性很高,在各大平台上 都有專屬的版本。 2. 用戶端可以用多種程式語言來進行資料庫的存取。
3. 以作業系統的 Kernel Thread 來達到多執行緒(Multi-Thread)。 4. 系統的密碼和個人使用權限設定,非常的安全而且靈活。 5. 所有經由網路傳送的密碼,都經過加密演算法的處理。 6. 資料表(Table)中的記錄(Record)大小可以是變動的,也可以是 固定的。 7. 所有的欄位都可以有預設值,而且可以進行資料表的修正和最 佳化。 8. 支援許多種類的欄位資料型態。 9. 支援多國語系。 10. Open Source,而且在非營利的圍範之內是免費的。 在 Client-Server 的架構裡,MySQL 就是用來提供外界存取資料的 Server 端資料庫,如圖 2-1 所示。 我們之所以會選擇 MySQL 來做為我們的後端資料庫,主要還是因 為它的存取速度和整體的查詢效率。在 n-tier 的網站結構中,資料 庫的連線建立與存取會比其他的工作更花費時間和資源,因此選擇一 個好的資料庫對我們教學系統整體運作效能的提升會有很大的幫 助。而且 MySQL 在性能上可以媲美高性能但是也高價位的 Oracle 商 用資料庫系統,再加上 PHP 支援度最好的資料庫就是 MySQL,因此使 用 MySQL 來與 PHP 搭配會是非常不錯的選擇。
2-6 Apache HTTP Server
Apache HTTP Server 是由 Apache Software Foundation(ASF)所 開發管理的一項專案,目的在完成一個安全、有效率、而且具有彈性 的 Web 伺服器,以提供和現在的 HTTP 協定標準同步的 HTTP 服務。關 於 Apache HTTP Server 的由來,在 1995 年的時候,有一群程式設計 師,他們把 Rob McCool 所開發出來的 NCSA HTTPd 網頁伺服器加上各 式各樣的 Patch 以加強它的性能,因此大家把這個經過各式各樣修補 而成的網頁伺服器稱為”A Patch Server”,之後取它的諧
音”Apache”作為正式命名。
Apache HTTP Server 雖然主要是由 ASF 負責管理的專案,但是仍 然完全依造自由軟體的原則與特色。任何人只要有興趣,都可以加入 Apache 的開發行列。而且可以依照自己的喜好修改原始碼,並且擁 有修改後的軟體版權。像 Apache HTTP Server 這樣依造自由軟體原 則所開發出來的軟體,通常都具有以下的優點: 1. 可靠 (Reliable) 而且穩定性佳 2. 高效能(High Performance) 3. 高度的安全性 (Security) 4. 高度的伸縮性 (Scalability) 5. 升級快速 6. 低成本
Apache HTTP Server 透過讀取各種模組的 Dynamic Linking Library(DLL)來支援各式各樣的功能。圖 2-2 是以 Apache 做為 Web Server 的架構。
圖 2-2 以 Apache 為基礎的 Web Server 架構
Apache 的穩定性,當然不在話下。瑞士的網路效能監視專家 SysControl AG 公司在 2000 年 2 月份,公佈了他們對瑞士最受歡迎 的一百大網站可靠度評比結果。SysControl AG 花了三個月的時間從 四個不同的地方每五分鐘探測一次每個受測網站,每個月的當機時間 結果如表 2-3 所示。顯然 Apache 的穩定性比其他須付費的 Web Server 軟體要高上許多。
表 2-3 各種 Web Server 軟體效能測試評比
當機時間 Apache IIS Netscape Andere
九月 5.21 10.41 3.85 8.72
十月 2.66 8.39 2.80 12.05
十一月 1.83 14.28 3.39 6.85
從 1996 年到目前為止,Apache 已經成為了世界上最受歡迎的 Web Server 軟體。Netcraft Web Server Survey 在 2002 年八月宣稱已經 有 63%的網站使用的 Web Server 就是 Apache。不論是應用在商用的 網站系統或是應用在像我們這樣的網路教學環境,Apache 無疑是最 好的選擇。
2-7 FrontPage FrontPage 是一套比 Notepad 還好用的 HTML 編輯器,它包含您 熟悉的所視即所得環境,還可以顯示 HTML 標籤於所視即所得及 HTML 畫面中您可以在所視即所得相似於 Microsoft Word 的編輯畫面中快 速地建立網頁內容,例如輸入文字、插入圖片、建立超連結及繪製表 格。 只要執行顯示標籤指令,便可以在所視即所得的編輯畫面中檢 視 HTML 標籤,然後若將滑鼠指標移到 HTML 標籤上,完整的標籤內容 便顯示在螢幕秘訣中,這是學習 HTML 的好工具。如果使用者懂得 HTML,則可以切換到相似於 Notepad 的 HTML 編輯畫面中編輯 HTML 原 始碼。 我們可以利用檢視畫面快速且容易地執行網站管理工作。例 如,使用中斷的超連結報告找出需要修復的超連結、慢速網頁報告顯 示不同速率的數據機所需的下載時間以便找出下載耗時的網頁、網站 內未曾連結的圖片及檔案則可以從未連結的檔案報告中顯示出來。而 在較舊的檔案報告可以列出某個時間內未曾更新的檔案。 近來最新的技術則包括編輯 HTML、動態 HTML、Script、ASP 和 階層樣式表 (CSS) — 只要在單一的 FrontPage 應用程式視窗內就 可以輕輕搞定。Microsoft Script 編輯器提供快速建立、編輯
Scripts 及偵錯的功能。Microsoft Visual Basic for Applications 6.0 允許建立強大的 FrontPage 解決方案整合 Microsoft Office 應 用軟體。可利用 Microsoft Visual Studio 開發系統的 Design Time Control 擴充 FrontPage 功能。
看完如上述大概的優點之後,是否覺得寫網頁很容易呢,的確 是,但存在著一項缺點,即是 FrontPage 的使用程式形式固定,容易 造成程式碼多而複雜且不易判斷的結果,因此在使用人性化編輯網頁 之後,若要從原始碼修改網頁,將對使用者造成莫大的不便。
三、教學內容概要
接下我們把教學內容大致整理出來,詳細如下: 3-1 堆疊 堆疊(Stack)是一種特殊的有序串列,它限制所有資料的加入與 取出(或刪除)僅在串列的一端進行,而此端稱為頂端(Top);好比 一個圓筒容器,只能在此容器固定的一端放入或取出物件,如同堆疊 運算上暗示了如果我們依序將 A,B,C,D,E 加入堆疊中,則 E 一定 是第一個自堆疊中取出的元素,如圖 3-1 表示: 圖 3-1 Stack 資料結構示意圖 (最頂端資料即是 TOP 所指的資料)由圖 3-1 可看出資料加入完畢後,資料 E 的確是第一個被取出 的。因此我們可知堆疊的資料進出乃是採用後進先出(Last In First Out,LIFO)的模式,相對的我們也可以說它是先進後出(First In Last Out,FILO)的模式。 我們可以分別利用加入(push)和取出(pop)兩動作來存取資 料,堆疊結構繼續如下所述。 3-2 堆疊的教學與程式實作解說 3-2-1 一般靜態的實作 1. 陣列(Array)結構定義 堆疊採用一維陣列,其所需的陣列空間宣告即為
stack[MAX_STACK_SIZE],此 MAX_STACK_SIZE 為 stack 中所能儲 存的元素個數,其程式定義則如程式 3-1: #define MAX_STACK_SIZE 100 /* 宣告堆疊的大小空間 */ typedef struct /*以結構體定義的堆疊元素*/ { int key; … /* 此處也可增加一些不同型別 的欄位 */ } element; element stack[MAX_STACK_SIZE]; /* 宣告一個堆疊陣列 */
int top = -1; /* 將頂端的值設成少於堆疊 底部 1 陣列單位,即表示當 top 等於-1 時,此堆疊為空! 由此可知當 top 值等於 MAX_STACK_SIZE 減 1 時此堆疊已滿 */ 程式 3-1 靜態堆疊的陣列(Array)結構定義程式 2 加入動作 Push: 加入動作的意思即是自堆疊的頂端放入資料,但先決條件是 要先判斷此堆疊是否已滿(stack_full),若滿則無法加入資料, 其程式如程式 3-2:
void push(int *top , element item) /* 加入動作內利用 top 指標來記錄 item 元素的加入 */ { if (*top >=MAX_STACK_SIZE-1) /* 加入元素前根據 堆疊所宣告的原理, 當 top 值等於或大於 MAX_STACK_SIZE 減 1 時即此堆疊已滿 */ { stack_full(); /* 若滿則呼叫 stack_full()函 式且傳回堆疊的 欄位內容 */ return; }
stack[++*top]=item; /* 若 top 不符合上 面的判斷式則將元 素 item 放入頂端加 1 的位置 */ } 程式 3-2 靜態堆疊的加入動作(Push)程式
註:
stack_full()函數說明:
此函數主要目的在於給程式使用者一個堆疊已滿的警告,可
直接印出堆疊已滿的警告訊息,如程式 3-3:
stack_full(){printf(”Stack is full!! And can’t push any item!!\n”); } 程式 3-3 堆疊的容量滿載程式 3. 取出動作 Pop: 取出動作的意思即是自堆疊的最上層取出資料,但先決條件 是要先判斷此堆疊是否已空(stack_empty),若空則無法取出, 其程式如程式 3-4:
element pop(int *top) /* 取出動作是利用 top
指標將頂端位置減一即 可 */ { if(*top==-1) /* 取出元素前根據堆疊 所宣告的原理,當 top 值 等於負 1 時即示此堆已
空,沒有東西可取出 */ return stack_empty(); /* 若空則呼叫 stack_empty()函式且 傳回堆疊已空的訊息 */ return srack[(*top)--]; /* 若堆疊中尚有元素, 則將 top 指標位置減 1 並 傳回堆疊的欄位內容 */ } 程式 3-4 靜態堆疊的取出動作(Pop)程式
註:
stack_empty()函數說明:
此函式主要目的在於給程式使用者一個堆疊已空的警告,可
直接印出堆疊已空的警告訊息,如程式 3-5:
stack_empty(){printf(”Stack is empty!! You can’t pop any item!!\n”); } 程式 3-5 堆疊的資料為空之程式 3-2-2 以動態鏈結串列的實作 1. 鏈結串列(Linked-list)結構定義: 鏈結串列是利用動態記憶體配置的技巧來使用記憶體,其基本用 途是在程式撰寫者無法預知需要使用多少記憶體空間時使用;鏈結串 列的基本結構圖則如圖 3-2 所示。
TOP item link item link item link 。。。 圖 3-2 動態鏈結堆疊之結構示意圖 (item 為資料儲存區) 之前提到以陣列結構來定義堆疊動作,現在我們也可以以另一資 料存取方式來定義堆疊結構,就是鏈結串列(Linked-list),他是依 宣告的資料形式(如我們用 typedef 所定義出含多型別的資料項)來 配置非連續空間,有效的利用記憶體上的零星不連續空間,因為他在 資料串上是以動態指定前後項位置,因此也解決陣列結構定義上的連 續記憶體空間限制,方便程式撰寫者來使用記憶體空間;即我們不必 擔心記憶體是否連續、是否夠用,就能依需要作堆疊。使用鏈結串列 定義堆疊的程式如程式 3-6 所示: #define MAX_STACKS 10 /* 宣告堆疊的最多個數 */ typedef struct /* 以結構體定義的堆疊元素 */ { int key; … /* 此處也可增加一些不同型別 的欄位 */ } element;
typedef struct stack *stack_pointer;
/* 宣告堆疊的指標結構 */
typedef struct stack { /* 將堆疊元素的雛型定出,
element item; 一個是資料項 item,
stack_pointer link; 一個是指標項 link */
};
stack_pointer top[MAX_STACK] /* 宣告出 top 指標,即頂端 */
2. 加入動作 Push:
加入動作主要是新增一符合結構體定義的記憶體空間,並利 用指標將資料項(也就是新增的堆疊元素)鏈結起來,完成如堆 疊定義的連續資料,並將該新增資料項由 top 指標指向之,即指 定其為頂端,其程式如程式 3-7 所示:
void push(stack_pointer *top,element item) /* 宣告要傳入 的參數型態 */ {stack_pointer temp = (stack_pointer)malloc(sizeof (stack));
/* 動態產生一
個記憶體空間 來使用 */
if( IS_FULL(temp)){ /*判別記憶體空
間是否已滿*/ fprintf(stderr,”The memory is full!!\n”);
exit(1); }
temp->item = item; /* 將資料存入
item 項 */
temp->link = *top; /* 利用 top 指標把
心節點指向原來 的頂端 */ *top = temp; /* 再將加入的元素 設成頂端 */ } 程式 3-7 動態堆疊的加入動作(Push)程式 3. 取出動作 Pop: 取出動作主要目的是將欲取出資料項其鏈結移除,並將 top 指標 移向前一個資料項,最重要的是在移除鏈結之後必須將不用的記憶體
空間釋放掉,因為程式一直不將資料釋放時,將極有可能造成記憶體 空間被佔而越來越少,恐造成無法預期之結果。其程式如程式 3-8 所 示:
element pop(stack_pointer *top){ /* 告需要傳遞的參
數型態 */
stack_pointer temp = *top; /* 宣告一指標 */
element item; /* 宣告一變數 */
if(IS_EMPTY(temp)){ /* 判別堆疊是否空
無元素 */ fprintf(stderr,”The stack is empty!!\n”); exit(1);
}
item = temp->item; /* 將 temp 指的元素
中的資料取出至新 的變數中 */
*top = temp->link; /* 並將頂端向下移
一位 */
free(temp); /*釋放不用的空間*/
return item; /* 傳回 item 值 */
} 程式 3-8 動態堆疊的取出動作(Pop)程式 3-3 佇列 佇列(Queue)是一種有序串列,它所有的加入動作發生在串列的 一端,所有的刪除動作發生在串列的另一端,其中加入的一端稱為尾 端(rear),而刪除的一端稱為前端(front)。佇列運算上暗示了如果 我們依序將資料 A,B,C 加入佇列中,則 A 一定是第一個自佇列刪除 的元素。佇列資料的進出採用先進先出(First In First Out,FIFO) 模式,我們可以利用 addq 和 deleteq 函式,分別處理存入和取出資 料等操作,佇列結構如圖 3-3:
圖 3-3 佇列結構示意圖 3-4 佇列的教學與程式實作解說 在這一節中,我們將分別以靜態與動態這兩種方法來實際說明佇 列(Queue)的結構表示法以及如何加入(addq)元素和刪除(deleteq) 元素。 在靜態方面,我們以陣列(Array)結構來實作。 在動態方面,我們以鏈結串列(Link-list)結構來實作。 3-4-1 一般靜態的實作 1. 陣列(Array)結構定義 在這裡,我們將採用一維陣列,再加上兩個變數 front 和 rear 來表示佇列(Queue),結構如圖 3-4:
圖 3-4 靜態佇列之結構示意圖 其 C 語言結構定義如程式 3-9: #define MAX_QUEUE_SIZE 100 /*定義佇列的大小*/ typedef struct{ /*以結構體來表示佇 列元素*/ int Key; /*佇列元素資料欄 位*/ ………… /*此處可再增加其它 欄位*/ } element; element queue[MAX_QUEUE_SIZE]; 程式 3-9 靜態佇列的陣列(Array)結構定義程式 ※底下為佇列 front 與 rear 的初始值: front = -1; rear = -1;
※底下為空佇列與滿佇列的判斷: front == rear /*此時佇列為空的*/ rear == MAX_QUEUE_SIZE-1 /*此時佇列為滿的*/ 2. 新增(addq)程式 若要新增元素到佇列中,主要的步驟如下: (1) 先檢查佇列是不是滿了。 (2) 如果佇列還沒滿,就將 rear 指標往前移動一格。 (3) 最後建立 rear 指標所指位置的陣列內容,再把元素 存入。 其 C 語言的表示法如程式 3-10 :
void addq(int *rear , element item) /* 增加元素到佇 列中 */ {
if(*rear==MAX_QUEUE_SIZE-1) /*佇列為滿的*/ {
print(“The Queue is full .\n”); return -1; } queue[++*rear]=item; /* 把新增元素 放到佇列中*/ } 程式 3-10 靜態佇列的加入動作(Addq)程式
3. 刪除(deleteq)程式 若要從佇列中刪除元素,其主要的步驟如下: (1) 先檢查佇列是不是空的。 (2) 如果佇列不是空的,就將 front 指標往前移動一格。 (3) 最後刪除 front 指標所指位置的元素。 其 C 語言的表示法如程式 3-11 :
element deleteq(int front , int rear)/*從佇列前端刪除 物件*/
{
if(front == rear) /*佇列為空的*/ {
printf(“The Queue is empty .\n”); return –1;
}
return queue[++front]; /*front 往後 移動一格,然後 取出欲刪除的前端 第一個元素*/ } 程式 3-11 靜態佇列的刪除動作(Deleteq)程式 4. 討論 這種以陣列表示的佇列,會有一個很大的缺點,我們可以 從 addq 和 deleteq 這兩個動作中看出,就是 front 和 rear 都是往同一個方向移動,當 rear 指到 MAX_QUEUE_SIZE-1 時,
就表示佇列已經滿了。如果我們還要對佇列作加入動作的 話,就必須對佇列內的元素作位移的動作,也就把元素往佇 列的前端移動以空出空間,否則就無法再加入元素。但由於 對佇列內的元素作位移動作必須耗費相當多的時間,在實作 上比較沒有效率,所以我們並不採用。為了解決這個問題, 我們採用另一個較有效率的表示法,就是環狀佇列(Circular Queue),這種表示法的實作我們將在 3-5 作詳細的介紹。 3-4-2 以動態鏈結串列實作 1. 鏈結串列(Link-list)結構定義 在這裡,我們將以鏈結串列(Link-list)的方法來表示佇列 (Queue),由於鏈結串列(Link-list)是動態記憶體分配,只 有在增加元素到佇列的時候,才會分配記憶體給新增的元 素,所以可以不用檢查佇列是否已滿。除非記憶體不足,否 則佇列是不會滿的。結構如圖 3-5: 圖 3-5 動態鏈結佇列示意圖
其 C 語言結構定義如程式 3-12:
#define MAX_QUEUE 3 /*定義佇列的大小*/
typedef struct queue queue_pointer; /*定義佇列的結構指 標型態*/
typedef struct queue { /*定義佇列的結構*/
element item; /*結構資料欄位*/
queue_pointer link; /*結構指標欄位*/ };
queue_pointer front[MAX_QUEUE] , rear[MAX_QUEUE];
/*宣告 front 指標和 rear 指標*/ 程式 3-12 動態佇列的鏈結串列(Linked-list)結構定義程式 2. 新增(addq)程式 若要新增(addq)一筆資料到此種佇列中,其主要的步驟如下: (1) 建立一個新節點,並且將資料存入。 (2) 檢查 front 是不是 NULL,即第一次存入資料到佇列中。 ◎如果是,則將 front 指向新節點。 ◎如果不是,則將 rear 所指節點的指標指向新節點。 (3) 最後將 rear 指向新節點。 其 C 語言的表示法如程式 3-13:
void addq(queue_pointer *front, queue_pointer *rear, element item)
{ /*增加元素到佇列中*/
queue_pointer temp=(queue_pointer) malloc(sizeof(queue)); /*動態分配記憶體空間
給新增的節點,並且宣告 指標 temp 指向它*/
if(!temp) /*表示記憶體已經滿了*/ {
printf(“The memory is full.\n”); return –1;
}
temp->item = item; /*將資料 item 放入新節點的
item 欄位*/
temp->link = NULL; /*將新節點的 link 欄位 指向 NULL*/ if(*front) /*用來判斷鏈結佇列是 否為空的時要作的動作*/ (*rear)->link = temp; /*此時的佇列並不是 空的,所以將 rear 目前所指的節點指 向新節點*/ else *front = temp; /*此時的佇列是空的, 所以新節點是佇列 第一個元素,然後將 front 指向新節點 */
*rear = temp; /*最後將 rear 指向新
節點 */ } 程式 3-13 動態佇列的加入動作(Addq)程式 3. 刪除(deleteq)程式 若要從此種佇列中刪除一筆資料,其主要的步驟如下: (1) 檢查 front 是不是 NULL,也就是判斷鏈結佇列是不是空的。 ◎如果是,則沒有資料可以刪除。 ◎如果不是,則將 front 指向下一個節點。 (2) 刪除第一個節點的資料。 (3) 釋放第一個節點所占有的記憶體空間。
其 C 語言的表示法如程式 3-14:
element deleteq(queue_pointer *front)
{ /*從鏈結佇列中刪除
元素*/
queue_pointer temp = *front; /*宣告一個指標 temp, 而且把這個指標指 向 front 所指的節點, 即要刪除的節點*/ if(*front == NULL)) /*表示鏈結佇列現在 是空的*/ {
printf(“The queue is empty.\n”); return –1;
}
*front = temp->link; /*將 front 移到下一個
節點*/ item = temp->item; /*將欲刪除的節點之 item 欄位的資料放 到變數 Item 裡*/ free(temp); /*釋放節點所占有的 記憶體空間*/ return item; /*回傳被刪除的值*/ } 程式 3-14 動態佇列的刪除動作(Deleteq)程式 3-5 環狀佇列(Circular Queue) 在這一節中,我們將分別以靜態與動態這兩種方法來實際說明環 狀佇列(Circular Queue) 的結構表示法以及如何加入(addq)元素和 刪除(deleteq)元素。
在靜態方面,我們以陣列(Array)結構來實作。 在動態方面,我們以鏈結串列(Link-list)結構來實作。 3-6 環狀佇列的教學與程式實作解說 3-6-1 一般靜態的實作 1. 陣列(Array)結構定義 當我們以陣列(Array)來實作佇列(Queue)的時候,若 佇列已滿時,就無法再存入任何資料。為了解決這個問題, 我們可以將表示佇列的一維陣列之尾端與開端理論上連接 在一起,也就是把佇列視為一個環(Circular),在當資料 存至陣列之尾端的時候,只要開端有空位,即可循迴至陣 列的開端繼續儲存。這樣的話,可以使得佇列在使用上變 得更有效率。這個有效率的表示法即所謂的環狀佇列 (Circular Queue)。 結構如圖 3-6 : 圖 3-6 環狀佇列示意圖
其 C 語言結構定義程式如程式 3-15: #define MAX_QUEUE_SIZE 4 /*定義佇列的大小*/ typedef struct{ /*以結構體來表示佇列元素*/ int Key; /*佇列元素資料欄位*/ ………… /*此處可再增加其它欄位*/ } element; element queue[MAX_QUEUE_SIZE]; 程式 3-15 靜態環狀佇列的陣列(Array)結構定義程式 在環狀佇列這種表示法中,front 永遠以逆時鐘方向指著佇列 中第一個元素的前一個位置,而 rear 則指向佇列目前最後一個元 素的位置。 ※底下為環狀佇列 front 與 rear 的初始值: front = 0; rear = 0; ※環狀佇列空與滿的判斷: 在下面兩張圖中,分別代表空的環狀佇列與滿的環狀佇列, 我們可以從圖中看出無論環狀佇列是空的或滿的,其表示法皆為 front = rear,如此一來,便會造成我們無法分辨環狀佇列到底 是空的還是滿的。所以,為了解決這個問題,於是我們便規定一 個大小為 MAX_QUEUE_SIZE 的環狀佇列最多只能存 MAX_QUEUE_SIZE-1 個元素。
2. 新增(addq)程式 若要新增(addq)一筆資料到環狀佇列中,其主要的步驟如下: (1) 將 rear 往前移動一格。 (2) 判斷環狀佇列是不是滿了。 ◎ 如果是,則無法加入元素,此時把 rear 往後退一格。 ◎ 如果不是,則把元素存到 rear 所指的位置。 其 C 語言的表示法如程式 3-16 :
void addq(int front, int rear, element item )
{ /*增加元素到環狀佇列*/
rear = (rear+1) % MAX_QUEUE_SIZE;
/*這一段是為了讓環狀 佇列能夠轉動,一旦 rear 已指到最後一個位置, 還能夠回到前面的位置 繼續存取*/ if(front == rear) /*判斷環狀佇列是否 已滿*/ {
printf(“The Circular Queue is full.\n”);
/*這個時候環狀佇列已滿*/
*rear=((*rear+ MAX_QUEUE_SIZE)–1) % MAX_QUEUE_SIZE;
/*將 rear 指標往後退移 動一個位置,也就是回到 前一個存取的位置*/ return; } queue[rear] = item; /*把新增元素放到環狀 佇列中*/ } 程式 3-16 靜態環狀佇列的加入動作(Addq)程式
3. 刪除( deleteq)程式 若要從環狀佇列中刪除一筆資料,其主要的步驟如下: (1) 判斷環狀佇列是不是空的。 1. 如果是,則沒有元素可以刪除。 2. 如果不是,則把 front 往前移動一格。 (2)刪除 front 所指位置的元素。 其 C 語言的表示法如程式 3-17 :
element deleteq(int front, int rear) /*從環狀佇列中
刪除元素*/ { element item;
if(*front == rear) /*判斷環狀佇列
是否為空的*/ {
printf(“The Circular Queue is empty.\n”); return;
}
front = (front+1) % MAX_QUEUE_SIZE;
/*這一段是為了 讓環狀佇列能夠 轉動,一旦 front 已指到最後一個 位置,還能夠回到 前面的位置繼續 執行刪除的動作*/ return queue[*front]; /*取出欲刪除的 元素*/ } 程式 3-17 靜態環狀佇列的刪除動作(Deleteq)程式
3-6-2 以動態鏈結串列實作 1. 鏈結串列(Link-list)結構定義 在這裡,我們將以鏈結串列(Link-list)的方法來表示環狀佇 列,而我們要到底要怎樣才能以鏈結串列來建立環狀佇列呢? 其實方法很簡單,首先我們先建立好一個基本的鏈結串列,接著 再把最後一個節點指向第一個節點就可以了。而現在所建立起來 的環狀佇列我們稱之為環狀鏈結串列(Circular-Link-list)。結 構如圖 3-7: 圖 3-7 環狀鏈結佇列之結構示意圖 其 C 語言結構定義如程式 3-18: #define MAX_QUEUE 3 /*定義佇列的大小*/
typedef struct queue queue_pointer;
/*定義佇列的結構指標型態*/
typedef struct queue { /*定義佇列的結構*/
element item; /*結構資料欄位*/
queue_pointer link /*結構指標欄位*/
};
queue_pointer front[MAX_QUEUE] , rear[MAX_QUEUE];
/*宣告 front 指標和 rear 指標*/
2. 新增(add_queue)程式 若要新增(addq)一筆資料到鏈結佇列中,其主要的步驟如下: (1) 建立一個新節點,並且將資料存入。 (2) 檢查佇列是不是空的。 ◎ 如果是,則將 front 指向新節點,並且把新節點的 link 欄位指向新節點自已。 ◎ 如果不是,則將 rear 所指的節點指向新節點,並且 把新節點指向 front 所指的節點。 (3) 把 rear 指向新節點。 其 C 語言的表示法如程式 3-19 :
void add_queue(queue_pointer *front , queue_pointer *rear , element item )
{
queue_pointer temp=(queue_pointer)malloc( sizeof(queue) ); /*動態分配記憶體空間給
新增的節點,並宣告指標 temp 指向它*/
if( !temp ) /*表示記憶體已經滿了*/
{
printf(“The memory is full.\n”); return -1;;
}
temp->item = item; /*把資料放到新節點*/
if( *front ) /*如果佇列不是空的*/
{
temp->link = *front; /*把新節點指向 fron 所指 的節點*/
(*rear)->link = temp; /*把 rear 所指的節點指向 新節點*/
}
else /*如果佇列是空的*/
{
front = temp; /*把 front 指向新節點*/
temp->link = temp; /*把新節點指向自已*/
}
rear = temp; /*把 rear 指向新節點*/
} 程式 3-19 動態環狀佇列的加入動作(Addq)程式 3. 刪除(delete_queue)程式 若要從鏈結佇列中刪除一筆資料,其主要的步驟如下: (1) 檢查 front 是不是 NULL,也就是判斷佇列是不是空的。 ◎ 如果是,則沒有資料可以刪除。 ◎ 如果不是,則判斷佇列中有幾個節點: ※ 如果只有一個節點,則把 temp 指向 front 所指 的節點,也就是要刪除的節點,然後再把 front 和 rear 指向 NULL。 ※ 如果有多個節點,則把 temp 指向 front 所指的 節點,也就是要刪除的節點,然後再把 front 指向 下一個節點,且把 rear 所指的節點指向現在 front 所指的節點。 (2) 刪除節點資料。 (3) 釋放節點所占有的記憶體空間。
其 C 語言的表示法如程式 3-20:
element delete_queue( queue_pointer *front , queue_pointer *rear )
{
queue_pointer temp
element item; /*item 用來放刪除的資
料*/
if( *front = =NULL ) /*如果佇列是空的*/
{
printf(“The queue is empty.\n”); return -1;
}
if( (*front)->link == (*front) ) /*如果佇列中只有一個節 點*/
{
temp = *front; /*把 temp 指向 front 所指 的節點*/
*front = NULL; /*把 front 指向 NULL*/
*rear = NULL; /*把 rear 指向 NULL*/
}
else /*佇列中有多個節點*/
{
temp = *front; /*把 temp 指向 front 所 指的節點*/
*front = temp->link; /*把 front 指向下一個 節點*/
(*rear)->link = *front /*把 rear 所指的節點 指向 front 所指的節點*/ } item = temp->item; /*把刪除的資料放到 item 中*/ free(temp); /*釋放節點所占有的記 憶體空間*/ return item; /*回傳被刪除的資料*/ } 程式 3-20 動態環狀佇列的刪除動作(Deleteq)程式
3-7 生活實例說明
1.Stack 實例說明
1.1 基本實例 甲、 由作業系統提供的系統堆疊,主要用途在程式執 行時儲存呼叫返回位址與作業系統執行程式時的作 業記錄(Activation Record)之儲存,所儲存的有 區域變數、各形式的參數值、返回位址(Return Address)、程式執行傳回值、…等等。 乙、 Compiler 做運算式解析時使用的方法,如中序表 示的算式可將其轉換成後序式或前序式表示法。 1.2 生活實例 (1) 衣櫥中衣服的堆積,取出與放入皆在頂端。如圖 3-8。 (2) 光碟存放桶(俗稱布丁桶)。如圖 3-8。 圖 3-8 堆疊生活實例示意圖2
.
Queue 實例說明 2.1 基本實例 大型主機的作業系統中,有一項機制就是工作佇列 (又稱 job spooling),他的運作方式是在一批資料輸入 時,先將它們儲存於磁碟之中,等資料讀取完備,在依據 資料要求性質作出動作,舉個例子: 當一群學生於機房下達列印資料後,主機並不會立 刻執行列印動作,而是將資料儲存於磁碟之中,待主機忙 碌之後,再將資料整批印出,此為工作佇列的運作方式. 2.2 生活實例 (1)水管中的水 假設有一連串的水流進水管中,當第一個部分的水由 水管的一端進入水管中之後,最後由水管另一端最先流出 的水一定是這一部份的水。 (2) 超市排隊付賬,先排隊者先付帳,後排隊者後付帳。 圖 3-9 佇列生活實例示意圖3-8 應用:以單一陣列實作一個堆疊及一個佇列 3-8-1 原理解說部分 接下來我們將以一個有限大小的陣列(Array),實作出同時具一 個堆疊(Stack)以及一個佇列(Queue)的功能。以下將分步驟說明 製作原理: ◎步驟一:先將陣列(Array)切成兩等份,並以變數 sep_line 記錄 堆疊與除列間的分界點,其餘的變數宣告大致如 top、
front、rear,所宣告的函式有靜態的 push()、pop()、
addq()、deleteq()等,函式僅有 push()、pop() 需作些微修改即可(即改變堆疊放入取出之方向),基本 架構的表示圖如圖 3-10: sep_line 環狀佇列部分 堆疊部分 陣列 x x x x、 、 、 x x (Array) 0 1 、 、 、 、、、 、、、 size-2 size-1
front rear top
圖 3-10 應用實作的基本架構圖 ◎步驟二:利用累加或累減變數 sep_line ,使當堆疊滿或佇列滿時 以變數 sep_line 當中介來調節彼此空間的借用,狀況如 下述: 狀況一:堆疊已滿,須向佇列方借陣列空間,描述如下: 1. 若佇列亦滿,則傳回警示訊息(如陣列已滿,無 法在加入任何資料)。 2. 若佇列未滿,可借到空間,則再有兩狀況:
2-1.佇列鄰近變數 sep_line 處的空間未使用,則將 變數 sep_line 值減一,可多出一陣列單位供堆疊 使用。但若此時變數 rear 值等於變數 sep_line 的值時,須將變數 rear 指回陣列開端,即陣列表 示的 s[0]處,就可以避免環狀佇列方面的錯誤, 如圖 3-11 所示。 sep_line 環狀佇列部分 堆疊部分 陣列 x x x x x 、、、 x x、 、 、 x x (Array) 0 1 、 、 、 size-1
front rear top 原分隔處 圖 3-11 堆疊借用空間後的說明圖(1) 2-2.佇列已使用鄰近變數 sep_line 處的陣列空 間,則將環狀佇列中由變數 front 所指的位置至 變數 sep_line 所指的位置中間的資料均向前移 動一陣列單位,因此可以空出一單位空間提供堆 疊來使用,當然在資料移動後也需要將 front 值 與 sep_line 值減一。如圖 3-12 所示。 sep_line 環狀佇列部分 堆疊部分 陣列 x x x x x x x 、、、 x x、 、 、 x x (Array) 0 1 、 、 、 size-1
front rear top 原分隔處
狀況二:佇列已滿,須向堆疊方借陣列空間,描述如下: 1.若堆疊亦滿,則傳回警示訊息(如陣列已滿,無法 在加入任何資料)。 2.若堆疊未滿,可借到空間,此時要先判斷佇列是否 已利用環狀功能把資料繞至前方,此時狀況再有 二: 2-1.變數 rear 與變數 sep_line 同值,即資料未環 繞至前方,可馬上將變數 sep_line 的值加一, 則向堆疊借空間給佇列成功。如圖 3-13 所示。 sep_line 環狀佇列部分 堆疊部分 陣列 x x 、 、 、 x x x x x x、、、x x (Array) 0 1 、、、 size-2 size-1
front rear top
圖 3-13 佇列借用空間前的說明圖(1) 2-2. 變數 rear 與變數 sep_line 不同值,即資料 已環繞至前方,此時須將資料向前移一單位,但 要先將最前方資料移動至變數 raer 所指處,再 整體向前移動一資料單位,則為變數 rear 與變 數 sep_line 同值的狀況,即可將變數 sep_line 的值加一,則向堆疊借空間給佇列成功。如圖 3-14 所示。
sep_line
環狀佇列部分 堆疊部分
陣列 x x 、 、 、 x x x x x x、、、x x (Array) 0 1 、、、 size-2 size-1
front rear top
圖 3-14 佇列借用空間前的說明圖(2)
3-8-2 程式解說部分
以下將對各程式片段做詳解,如程式 3-21:
typedef struct mix_tag{ /*以結構體宣告程式基
element s[size]; 本所需的變數*/ int top,front,rear; int sep_line; } Mix_type; void initialize(Mix_type *ptr) /*設定陣列的初始狀況*/ { ptr->top = size – 1; /*堆疊初始位置*/ ptr->front = 0; /*佇列初始位置*/ pte->rear = 0; pte->sep_line = size / 2; /*用標記將陣列畫分為 } 二*/
void stackfull(Mix_type *ptr) /*判斷堆疊滿時,所面對
{ int i; 所有狀況的副程式*/
if((( ptr->rear + 1 ) % ptr->sep_line) == ptr->front) { printf(“ Array full !! “); /*判斷佇列是否亦滿,
exit(1); 若滿則結束副程式*/
}
else if (ptr->front < ptr->rear ) /*佇列未滿且尚未環繞
{ ptr->sep_line--; 至前方*/
if( ptr->rear == ptr->sep_line )/*若變數 rear 鄰近中
ptr->rear = 0; 界點,將 rear 移至陣列
} 前端*/
else
{ for( i = ptr->front; i < ptr->sep_line; i++ )
ptr->s[i-1] = ptr->s[i]; /*若佇列已滿且 rear 繞
ptr->sep_line--; 至前方,則將 front 至 ptr->front--; sep_line 中間的資料向 } 前移動一資料單位以供 } 堆疊借用*/ void queuefull(Mix_type *ptr) /*判斷佇列滿時,所面對 { int i; 所有狀況的副程式*/
if( ptr->top + 1 == ptr->sep_line )
{ printf(“ Array full !! “); /*判斷堆疊是否亦滿,
exit(1); 若滿則結束副程式*/
}
else /*堆疊未滿的狀況如下*/
{ if ( ptr->rear != sep_line ) /*佇列 rear 是否鄰近中 界點,是則直接跳過 if 判斷式*/
{ ptr->s[sep_line] = ptr->s[0];
/*先將最前方資料移到 rear 所指處*/
for ( i = 1; i < ptr->rear; i++ )
ptr->s[i-1] = ptr->s[i];/*再將整個資料項前移
} sep_line++; /*再調整中界位置即完 ptr->front++; 成借用空間*/ } } 程式 3-21 應用範例程式解說 3-8-3 結論 本程式作法的優點特色在於堆疊與佇列兩者能動態支援對方 的儲位需求,利用累加或累減變數 sep_line,使堆疊滿時能向 佇列借用空間,佇列滿時能向堆疊借用空間,程式原理最大癥結 在環狀佇列是否有環繞至陣列前方,因此不管是堆疊滿或佇列滿 均需要檢查佇列是否已經環繞,釐清此問題後,程式便能一目了 然,容易的使用了。
第四章 系統分析及設計
一個系統在開發的過程中,如果沒有經過良好的規畫和設計,在 開發的過程中一定會遇到重重的困難。尤其是當系統中的各項不同性 質的功能,如果沒有規畫成專屬的子系統,那麼各項不同性質的功 能,可能會因為不當的功能相依性,造成系統在開發上,以及維護上 各種難以解決的問題。 因此,為了使我們的系統盡量達到功能模組化的目標,以提高系 統開發的效率,並且方便日後的維護,我們把主系統畫分為若干個子 系統。 圖 4-1 為主系統架構圖,共包含了四個子系統。 圖 4-1 主系統架構圖4-1 主要教學內容 這是提供給一般註冊學生所使用的子系統,一共具有八個功 能。最主要的功能是 “教學內容及動畫呈現”,為最主要的教 學內容課程; “系統功能簡介” 向使用者介紹系統的目的以及 使用方式; “生活實例” 提供一些 Stack 以及 Queue 在應用上 的實例介紹; “題庫測驗”提供使用者學習評量的地方;系統 會記錄使用者的成績,供教師或管理者參考使用; “討論板” 為使用者詢問問題與意見交流的園地; “參考資料 ”提供使用 者額外的學習資訊; ”批評與指教 ”提供使用者聯繫系統管理 者以及教師的管道; ”登出系統” 則會強制清除 COOKIE 內容, 並保存使用者的使用時數等資料,以供管理系統參考使用。 圖 4–2 教學子系統架構圖
以下各小節內容針對圖 4-2 中主要的教學內容加以說明。 在使用者使用登入系統之後,進入迴轉選擇頁面,選下將 要使用的八項功能,其中一項【進入教學頁面】將給予使用 者學習有關堆疊與佇列原理相關互動式之學習網頁,其進入 教學架構如圖 4-3: 圖 4-3 進入教學之架構圖
接下來將分節個別介紹堆疊與佇列的教學流程,如下所 列。 4-1-1 堆疊(Stack)教學內容場景設計 於開頭動畫後選擇頁面中,選擇進入堆疊教學後將有一 連串以 FLASH 製作成之資料以供學習,讓使用者知道堆疊結 構、程式寫法等訊息,其內容如堆疊基本原理架構、資料加 入動作原理、資料取出動作原理、加入動作程式說明、取出 動作程式說明、…等等,並且有靜態(ARRAY 製作)、動態 (LINKED-LIST 製作)之分。 操作流程以左方鏈結列為主,鏈結列上半部以說明為主, 依照構想有動態與靜態之分,分別是以鏈結搭上框架(frame) 顯示;同理,鏈結列下半部的程式解說也是分有靜態與動態, 如圖 4-5。 接下來我們以圖 4-4 來說明堆疊教學頁面的架構: 圖 4-4 堆疊教學頁的架構圖
教學頁面的特色在網頁上能跟使用者有所互動,以分頁、分 步驟的方式來達成,若使用者對現有頁面有無法理解之原理,可 立即利用左方鏈結或該頁面之上一步來得到解說,於程式方面採 用 STEP BY STEP 的操作方式給予使用者說明(如圖 4-5),讓使 用者針對程式中細部程式碼能一覽無疑,達到看的懂、教的通的 地步,因此使用者更能在接下來使用題庫測驗自己的學習與認識 教學程度有多少。 圖 4-5 堆疊教學頁面的互動式操作(此例可按下一步進行步驟三) 4-1-2 佇列教學內容場景設計 於開頭動畫後選擇頁面中,選擇進入佇列教學後將有一 連串以 FLASH 製作成之資料以供學習,讓使用者知道佇列與 環狀佇列的結構、程式寫法等訊息,其內容如佇列基本原理
架構、資料加入動作原理、資料刪除動作原理、加入動作程 式說明、刪除動作程式說明、…等等,並且有靜態(ARRAY 製作)、動態(LINKED-LIST 製作)之分。 操作流程以左方鏈結列為主,鏈結列上半部以說明為 主,依照構想有動態與靜態之分,分別是以鏈結搭上框架 (frame)顯示;同理,鏈結列下半部的程式說明也是分有靜 態與動態,如圖 4-6 : 圖 4-6 佇列教學頁面的互動式操作 接下來我們以圖 4-7 來說明佇列教學頁面的架構: 在進入佇列教學頁後,可以選擇要作佇列教學或是程式說明。 若選擇要作佇列教學的話,在這邊,我們把教學內容分為 佇列與環狀佇列兩個部份,給使用者選擇,其中每個部份各
分為靜態(Array 製作),與動態(Linke-List 製作)。 若選擇要作程式說明的話,在這邊,我們也把內容分為佇 列與環狀佇列兩個部份,供使用者選擇其中每個部分亦分為 靜態(Array 製作)與動態(Linked-List 製作),架構如圖 4-7 所示。 圖 4-7 佇列教學頁的架構圖 4-1-3 題庫測驗規畫 題庫測驗是用來評量使用者學習效率最好的工具。但是傳統 的題庫測驗都有一個缺點,那就是題目內容、出題順序以及答案 的選擇項目都是固定不變的。因此使用者在經過多次測驗之後,
所得到的成績,就變得很不客觀了。因此,我們改變傳統的設計 方式,將題庫測驗的架構設計如下: 1. 題目依難易度來區分,總共分為 Lv1、Lv2 以及 Lv3 三個等級, 使用者在做答前,可以選擇題目的難度。但是在第一次接受題 庫測驗的時候,只能進行 Lv1 難度的測驗。 2. 每次由題庫中隨機選出不重複的十個題目,供使用者回答,並 且每個題目的答案選項順序為隨機出現,每次都有變化。 3. 使用者在答完十題以後,由系統來統計使用者的答題正確率。 依照使用者的答題正確率以及題目的難度等級,使用者可以獲 得固定的累積分數。同時,系統會判斷使用者該等級的累積分 數是否達到一定的標準以判定使用者的升級與否。如果升級, 那麼以後就可以進行難度更高一級的測驗。 4. 使用者每次的測驗結果,均會由系統存入資料庫中保存。以提 供使用者學習成效評估系統之用。 5. 為了提高使用者的參與感,並且增加測驗的趣味性,每個題目 在出題之後,均會開始進行倒數計時。時間一到,如果使用者 還沒作答,那麼該題算答錯,並且接著進行下一題。
表 4-1 為每個等級測驗的答對題數以及所得到的績分分配。 每個等級的題目每 10 題一定要答對 8 題以上,才能獲得積分。 Lv1 的題目比較容易,所以每次獲得的績分比較少,全對得 3 分,對 9 題 2 分,對 8 題 1 分,對 8 題以下就沒有積分。其它等級的配分情 形依此類推。 表 4-1 成績與累績分數分配表 測驗等級 答對題數 得到績分 10 題 3 分 9 題 2 分 Lv 1 8 題 1 分 10 題 5 分 9 題 3 分 Lv 2 8 題 1 分 10 題 5 分 9 題 3 分 Lv3 8 題 1 分 測驗的流程如圖 4-8。 一開始由系統向使用者說明測驗規則,接下來由使用者選擇題目的 等級。然後,由系統提示使用者準備開始接受測驗。此時,系統會準備 好要讓始用者回答的題目,接著一一將題目交給使用者回答,並且計算 使用者的答題率。最後再把使用者的答題結果輸出到使用者的螢幕上, 並同時將資料寫入資料庫中保存,以供下次測驗累計之用。
4-1-4 討論區 討論區是提供使用者討論問題和提供建議最方便的管道。由於這 個部份的系統資源使用率並不會很大,因此為了降低資料庫系統的負 擔,討論區的部份,我們使用功能較簡便的 CGI board 來進行修改, 使它的風格和介面能夠和我們的主系統一致,然後再進行整合。 4-2 訪客子系統 訪客子系統為教學子系統的功能簡化模組,主要的功能為: 提供未註冊使用者參考系統功能之用,並且讓訪客了解註冊成為 正式學員所能得到的服務為何。 圖 4-9 為訪客子系統架構圖。 圖 4-9 訪客子系統架構圖
4-3 註冊認證子系統
在我們的系統中,使用者依權限來 區分,一共分為四種不同 的等級;分別為 Guest、General User、Manager 和 Supervisor。 Guest 不須登入,但是只能參觀,不能使用大部份的教學資源。 General user 就是一般通過註冊的學生,可以使用所有的教學資 源、線上測驗和討論區。Manager 管理學生的資料和追蹤使用者 的學習歷程。Supervisor 可以改變使用者的權限和更改 Supervisor 使用者之外的使用者資料,這是系統在初期安裝的時 候內建的帳號,不能透過管理介面更動資料。 透過 PHP 的程式 API,我們使用到了瀏覽器的 COOKIE 技術來 記錄使用者的使用資訊;包含使用者名稱、登入密碼、使用者權 限旗標、使用者總登入次數、系統使用總時數。我們將 COOKIE 的存活時間設定為 3 小時。使用者在每次登入系統過了 3 小時以 後,如果還沒登出,系統會自動為使用者執行登出的動作,把一 些具有保存價值的資料寫入資料庫中。 圖 4-10 為整個註冊認證子系統的流程圖。 使用者在進入系統,觀看完開頭動畫以後,系統便檢查使用者 cookie 資訊。若存在 cookie,則由系統自動幫使用者登入,否 則要求使用者登入。已註冊的使用者,在登入資料以後,由系統 判斷是否為合法的使用者。若是合法的使用者,則判斷使用者權 限,再依權限來開放系統功能,若是不合法的使用者,則顯示錯 誤訊息。在登入頁,未註冊的使用者可以進行註冊。系統會一一 檢查使用者在註冊時所輸入的資料是否正確。再將使用者的註冊 資料寫入資料庫中。
4-4 管理者子系統 管理者子系統提供教師以及系統管理員使用,管理學生使用 者的註冊資料功能。除此之外,還可以參考系統根據資料庫中的 記錄所繪製的 ”學生個人學習成效條狀圖“ 來作為學習效率 的評估。 管理者子系統所提供的管理介面,對資庫料中的資料直接進 行管理因此不須要進入資料庫系統中進行一些繁雜的管理工 作。這對系統管理者以及教師來說,是一項相當方便的功能。 圖 4-11 為管理者子系統流程圖。 系統在判定使用者具有管理者權限以後,將開放管理系統供 登入的使用者使用。在管理系統中,管理者可以進行各項註冊使 用者資料的管理功能,以及使用者學習效率評估。
4-5 資料庫設計 系統中的資料庫,一共存放了兩種類型的資料表,一種是與使用 者及系統相關資訊的資料表,另一種是題庫相關的資料表。 4-5-1 使用者資料表設計 未經正規化的使用者資料表內容定義如下: user_profile 資料表欄位(括號內為欄位可存放的資料長度): user_id varchar(20) //使用者帳號 password varchar(60) //登入用的密碼(使用 md5 演算 法進行編碼)
email_addr varchar(30) //Email 位址 name varchar(10) //真實姓名 sex varchar(1) //性別 birthday varchar(10) //生日 occupation varchar(2) //從事的工作 edu_background varchar(1) //教育程度 phone_no varchar(15) //電話號碼 mobile_phone_no varchar(10) //手機號碼 pwd_req_question varchar(1) //遺失密碼時,所要回答的問 題代號 pwd_req_ans varchar(20) //遺失密碼時,問題的解答 position varchar(1) //階級權限 1:Supervisor
// 2:Manager 3:General User visit_count(3) //登入次數
visit_time(6) //登入總時數