大二時寫的數據結構課程設計,好幾個朋友的推薦,現在放到博客了,希望對大家有幫助!
任務書
p 設計內容
設計與實現靜態查找表、基於二叉排序樹的動態查找表及HASH表等三種中的任意兩種查找表結構及其抽象數據類型;以一本英文電子書(如英文小說,科普讀物或聖經之類的社會書籍,書的篇幅不少於2萬次單詞)作為單詞文本數據來源,使用上述查找表ADT,通過讀取電子書而建立對應的兩種查找表,以單詞作為關鍵字,單詞在書籍中出現的次數及每次出現的頁碼,行號等信息作為查找表數據元素屬性;通過理論與實際測試結果對比分析兩種查找表性能。
p 設計要求
(1) 靜態查找表ADT要求實現Create、Destroy、Search、Traverse等操作,另外靜態查找表同時要求采用某種排序算法Sort對其排序,形成無序存儲與有序表存儲兩種物理存儲,並同時實現在有序表上的二分查找Search_Bin,且作為性能對比分析的一種情形。
(2) 動態查找表ADT要求實現InitDSTable、DestroyTable、SearchDSTable、InsertDSTable、DeleteDSTable、TraverseDSTable等操作,以二叉鏈表為物理存儲結構。
(3) HASH表要求實現InitHash、DestroyHash、SearchHash、InsertHash、DeleteHash、TraverseHash等操作,設計合理的HASH函數與沖突解決辦法,並在報告中分析說明選擇理由。
(4) 一個單詞的多次出現可以由鏈表表示,形成類似於倒排索引的結構。查找表數據以文件形式保存,如果在程序重啟動時能夠從查找表文件恢復查找表,或界面友好,或增加了有意義的功能等,具有一定特色,則給予鼓勵,酌情加分。但是,如果只實現了其中一種查找表,則綜合成績不超過75分。
引言
1.1 課題背景與意義
數據結構在計算機科學界至今沒有標准的定義。個人根據各自的理解的不同而有不同的表述方法:
Sartaj Sahni在他的《數據結構、算法與應用》一書中稱:“數據結構是數據對象,以及存在於該對象的實例和組成實 例的數據元素之間的各種聯系。這些聯系可以通過定義相關的函數來給出。”他將數據對象(data object)定義為“一個數據對象是實例或值的集合”。Clifford A.Shaffer在《數據結構與算法分析》一書中的定義是:“數據結構是 ADT(抽象數據類型Abstract Data Type) 的物理實現。”
Lobert L.Kruse在《數據結構與程序設計》一書中,將一個數據結構的設計過程分成抽象層、數據結構層和實現層。其中,抽象層是指抽象數據類型層,它討論數據的邏輯結構及其運算,數據結構層和實現層討論一個數據結構的表示和在計算機內的存儲細節以及運算的實現。數據結構具體指同一類數據元素中,各元素之間的相互關系,包括三個組成成分,數據的邏輯結構,數據的存儲結構和數據運算結構。
在日常工作和學習中,我們會遇到統計一個文章里面所包含的單詞或者詞語。然而現在這樣的統計軟件在網絡上特別多,作為一個學計算機編程的學生,我覺得有必要了解一下其核心功能以及算法實現。通過此次設計,可以對上學期學習的數據結構課程的內容做一個總結,感受真正用上學過的算法思想,這對以后的學習以及工作也有很大的幫助。
1.2 重要意義
一般認為,一個數據結構是由數據元素依據某種邏輯聯系組織起來的。對數據元素間邏輯關系的描述稱為數據的邏輯結構;數據必須在計算機內存儲,數據的存儲結構是數據結構的實現形式,是其在計算機內的表示;此外討論一個數據結構必須同時討論在該類數據上執行的運算才有意義。
在許多類型的程序的設計中,數據結構的選擇是一個基本的設計考慮因素。許多大型系統的構造經驗表明,系統實現的困難程度和系統構造的質量都嚴重的依賴於是否選擇了最優的數據結構。許多時候,確定了數據結構后,算法就容易得到了。有些時候事情也會反過來,我們根據特定算法來選擇數據結構與之適應。不論哪種情況,選擇合適的數據結構都是非常重要的。
選擇了數據結構,算法也隨之確定,是數據而不是算法是系統構造的關鍵因素。這種洞見導致了許多種軟件設計方法和程序設計語言的出現,面向對象的程序設計語言就是其中之一。
1.3 課程設計的主要研究工作
在計算機科學中,數據結構是一門研究非數值計算的程序設計問題中計算機的操作對象(數據元素)以及它們之間的關系和運算等的學科,而且確保經過這些運算后所得到的新結構仍然是原來的結構類型。
“數據結構”作為一門獨立的課程在國外是從1968年才開始設立的。 1968年美國唐·歐·克努特教授開創了數據結構的最初體系,他所著的《計算機程序設計技巧》第一卷《基本算法》是第一本較系統地闡述數據的邏輯結構和存儲結構及其操作的著作。“數據結構”在計算機科學中是一門綜合性的專業基礎課。數據結構是介於數學、計算機硬件和計算機軟件三者之間的一門核心課程。數據結構這一門課的內容不僅是一般程序設計(特別是非數值性程序設計)的基礎,而且是設計和實現編譯程序、操作系統、數據庫系統及其他系統程序的重要基礎。
計算機是一門研究用計算機進行信息表示和處理的科學。這里面涉及到兩個問題:信息的表示,信息的處理 。 而信息的表示和組織又直接關系到處理信息的程序的效率。隨着計算機的普及,信息量的增加,信息范圍的拓寬,使許多系統程序和應用程序的規模很大,結構又相當復雜。因此,為了編寫出一個“好”的程序,必須分析待處理的對象的特征及各對象之間存在的關系,這就是數據結構這門課所要研究的問題。眾所周知,計算機的程序是對信息進行加工處理。在大多數情況下,這些信息並不是沒有組織,信息(數據)之間往往具有重要的結構關系,這就是數據結構的內容。數據的結構,直接影響算法的選擇和效率。
計算機解決一個具體問題時,大致需要經過下列幾個步驟:首先要從具體問題中抽象出一個適當的數學模型,然后設計一個解此數學模型的算法(Algorithm),最后編出程序、進行測試、調整直至得到最終解答。尋求數學模型的實質是分析問題,從中提取操作的對象,並找出這些操作對象之間含有的關系,然后用數學的語言加以描述。計算機算法與數據的結構密切相關,算法無不依附於具體的數據結構,數據結構直接關系到算法的選擇和效率。運算是由計算機來完成,這就要設計相應的插入、刪除和修改的算法 。也就是說,數據結構還需要給出每種結構類型所定義的各種運算的算法。
數據是對客觀事物的符號表示,在計算機科學中是指所有能輸入到計算機中並由計算機程序處理的符號的總稱。 數據元素是數據的基本單位,在計算機程序中通常作為一個整體考慮。一個數據元素由若干個數據項組成。數據項是數據的不可分割的最小單位。有兩類數據元素:一類是不可分割的原子型數據元素,如:整數"5",字符 "N" 等;
另一類是由多個款項構成的數據元素,其中每個款項被稱為一個數據項。例如描述一個學生的信息的數據元素可由下列6個數據項組成。其中的出生日期又可以由三個數據項:"年"、"月"和"日"組成,則稱"出生日期"為組合項,而其它不可分割的數據項為原子項。關鍵字指的是能識別一個或多個數據元素的數據項。若能起唯一識別作用,則稱之為 "主" 關鍵字,否則稱之為 "次" 關鍵字。數據對象是性質相同的數據元素的集合,是數據的一個子集。數據對象可以是有限的,也可以是無限的。
數據處理是指對數據進行查找、插入、刪除、合並、排序、統計以及簡單計算等的操作過程。在早期,計算機主要用於科學和工程計算,進入八十年代以后,計算機主要用於數據處理。據有關統計資料表明,現在計算機用於數據處理的時間比例達到80%以上,隨着時間的推移和計算機應用的進一步普及,計算機用於數據處理的時間比例必將進一步增大。
系統需求分析與總體設計
2.1 系統需求分析
對單詞數量不少於2萬字的英文小說進行字符統計,用三種數據結構來實現,分別是基於順序表的實現、基於動態查找表以二叉搜索樹為結構來實現、基於HASH表的實現。抽象數據類型由單詞、出現次數、頁碼、行數組成。計算結果以文本文件的形式保存到本地目錄。以QT為用戶界面,以C語言為編程語言。
2.2 系統總體設計
(1) 首先用戶通過打開文件或者復制粘貼的方式把要分析的內容放在用戶界面上的文本框。文本框的內容用戶可以自己輸入或更改,完成后通過相應的按鈕進行計算並顯示。由於有三種數據結構來實現,因此需要把計算內容分別顯示。
(2) 基於順序表的實現有兩種,有序存儲結構和無序存儲結構。給用戶提供兩個按鈕來相應兩種結構的結果輸出。創建有序存儲先從文本內容里面取單詞,把取單詞的部分寫成單獨的函數,以便后序繼續使用此函數來取單詞,減少代碼量。然后從現有的存儲結構里面進行查找,如果找到了則單詞數目加一,否則進行插入。查找函數以折半查找算法為核心,作為與無序表性能對比分析的一種情形。為了更好的顯示出兩種存儲結構的優缺點,在這些函數運行時進行計時,當所有單詞統計出來以后,把總時間顯示到界面,以便用戶對比分析結果。表創建完成后進行遍歷輸出,輸出的內容有單詞內容,單詞出現次數、單詞出現的頁碼以及行數,所以以表格的形式在界面上進行顯示。
(3) 基於動態查找表以二叉搜索樹為結構來實現。首先從用戶輸入的內容里面進行讀取單詞,然后在現有的數據里面進行查找,如果沒有找到則進行創建。給用戶提供三種遍歷方式,前序、中序、后序。同樣,在此部分程序運行時進行計時,最后結果在界面上顯示,以便進行對比分析。
(4) 基於HASH表的實現,以每一個單詞的第一與第二個字母的ASCLL值的和作為哈希值進行創建,以線性探索來處理沖突,哈希表長度為52。在此部分程序運行時進行計時,最后把結果以表格的形式顯示在界面上。
(5) 計算並輸出完成后,用戶可以保存計算結果,保存的類型有txt、doc。保存位置由用戶決定,用戶打開對應的文件夾並輸入文件名以后進行輸出。
(6) 提供搜索功能,輸入單詞以后進行查找,找到單詞以后進行定位,並使用QT內部函數給單詞染色並突出顯示。
(7) 用戶界面上的所有按鈕可以用對應的快捷鍵來控制。QT界面引用CSS樣式表來設置界面顏色,總共提供四種風格。
程序整體流程圖為如下:
圖 2-1 系統整體運行流程圖
系統詳細設計
3.1 有關數據結構的定義
一共有四種數據結構,順序存儲結構、二叉樹存儲結構、HASH表存儲結構、行頁數存儲結構、高頻詞匯存儲結構。
(1)順序存儲結構
包含單詞內容、單詞出現次數、行數、頁數,詳細如下表:
表3-1 順序存儲結構數據類型
數據項 |
數據類型 |
名稱 |
單詞內容 |
Char [] |
word |
出現次數 |
Int |
count |
行、頁數 |
row_next * |
row_head |
順序表的邏輯結構:
圖 3-1 順序表的邏輯結構
(1)二叉樹存儲結構
包含單詞內容、單詞出現次數、指向行頁數的指針、指向左右結點的指針,詳細如下表:
表 3-2 二叉樹存儲結構數據類型
數據項 |
數據類型 |
名稱 |
單詞內容 |
Char [] |
word |
出現次數 |
Int |
count |
行、頁數 |
row_next * |
row_head |
左孩子結點 |
struct DtList * |
Lchild |
右孩子結點 |
struct DtList * |
Rchild |
二叉樹邏輯存儲結構如下圖:
圖 3-2 二叉樹邏輯存儲結構
(1)HASH表存儲結構
包含單詞內容、單詞出現次數、指向行頁數的指針, 詳細如下表:
表 3-3 HASH表存儲結構類型
數據項 |
數據類型 |
名稱 |
單詞內容 |
Char [] |
word |
出現次數 |
Int |
count |
行、頁數 |
row_next * |
row_head |
指向下一個結點的指針 |
struct Link_Node * |
next |
HASH表邏輯存儲結構如下圖:
(1)行頁數存儲結構
包含行數、頁數、指向下一個結點的指針,詳細如下表:
表 3-4 行頁存儲結構類型
數據項 |
數據類型 |
名稱 |
行數 |
Int |
row |
頁數 |
Int |
page |
指向下一個結點的指針 |
struct row_next * |
next |
行頁結構邏輯存儲結構如下圖:
(1)高頻詞匯存儲結構
包含單詞內容、出現次數,詳細如下表:
表 3-5 高頻詞匯存儲結構類型
數據項 |
數據類型 |
名稱 |
單詞 |
Char [] |
word |
次數 |
int |
count |
高頻詞匯邏輯存儲結構:
3.1 主要算法設計
這部分主要描述系統中的模塊實現的流程,可采用文字配合流程圖的方式表示各模塊的算法思想及流程。
- 有序存儲
首先初始化有序表,讀取單詞,從原有的順序表中進行折半查找,如果找到了則進行單詞數增加,並記錄行頁數。如果沒有找到,則進行插入。流程圖如下圖:
- 無序存儲
無序表創建過程與有序表一樣,只是在查找的時候不能用折半查找來實現,只能從頭開始一一比較。
- 二叉搜索樹
二叉搜索樹實現,首先獲取內容取單詞,創建二叉樹,並在原來基礎上查找結點,找到了則進行單詞數目增加,並記錄行頁數。沒有找到則進行插入。讀取文件完成后進行輸出,根據用戶需求分別用三種遍歷來輸出,輸出完成后計算出高頻詞匯,進行輸出,最后記錄運行總時間。流程圖如下:
- HASH表
HASH表實現流程基本上也一樣,實現的具體函數功能有所不一樣。下圖是整體實現過程:
系統實現與測試
4.1 系統實現
- 結構體
(1) 順序存儲結構
包含單詞內容、單詞出現次數、指向行頁數的指針
1 typedef struct 2 3 { 4 5 char word[MAX_CHARACTER];// 存儲單詞,不超過50個字符 6 7 int count; // 單詞出現次數 8 9 row_next *row_head; //指向行頁數的指針 10 11 row_next *row_tail; //指向最后一個(方便后序插入) 12 13 } ElemType; 14 15 16 17 typedef struct 18 19 { 20 21 ElemType *elem; // 存儲空間基址 22 23 int length; // 當前長度 24 25 int listsize; // 當前分配的存儲容量 26 27 } SqList;
(2) 搜索二叉樹存儲結構
包含單詞內容、單詞出現次數、指向行頁數的指針、指向左右結點的指針
1 typedef struct 2 3 { 4 5 char word[MAX_CHARACTER]; // 存儲單詞,不超過50個字符 6 7 int count; // 單詞出現次數 8 9 row_next *row_head; //指向行頁數的指針 10 11 row_next *row_tail; //指向最后一個(方便后序插入) 12 13 }DtElemType; //數據類型 14 15 16 17 typedef struct DtList 18 19 { 20 21 DtElemType elem; //存儲單詞 22 23 struct DtList *Lchild,*Rchild; //左孩子以及右孩子 24 25 }DtList;
(3) HASH表存儲結構
包含單詞內容、單詞出現次數、指向行頁數的指針
1 typedef struct Link_Node 2 3 { 4 5 char word[MAX_CHARACTER]; // 存儲單詞,不超過50個字符 6 7 int count; //單詞出現次數 8 9 row_next *row_head; //指向行頁數的指針 10 11 row_next *row_tail; //指向最后一個(方便后序插入) 12 13 struct Link_Node *next; 14 15 }Link_Node; 16 17 18 19 typedef struct Hash_Header 20 21 { 22 23 Link_Node *Link_head; //哈希表頭 24 25 }Hash_Header;
(4) 行頁數存儲結構
包含行數、頁數
typedef struct row_next{ int row; //行數 int page; //頁數 struct row_next *next; //指向下一個單詞的行數 }row_next;
下面分別介紹具體實現的函數:
- 取單詞 pickword
參數為文件地址,字符數組,行數。從文件地址所指的文件中依次讀取一個字符,一律轉換為小寫字符保存在目的單詞數組中。目的字符數組長度定義為50個字符,如果超過了進行返回。當遇到換行符時行數增加,遇到非字母字符時讀取結束,返回讀取到的單詞。具體過程如下圖:
- HASH_founc函數
實現HASH表時,哈希值用每一個單詞的第一個字符與第二個字符的ascll碼相加再與HASH表長度取余
- SqList_search_disorder無序表查找函數
實現無序表時,需要進行單詞的搜索,但這時候很難實現有效的查找算法,只能從表頭開始一一比較。
- SqListBSearch順序表二分法查找
實現有序表時,需要進行單詞的搜索,由於創建表時按照字母字典循序創建的,因此查找可以使用二分查找來實現,可以節省時間,效率高。
- SqListInit順序表初始化
構造一個空的順序表,分配內存,並初始化表長度,表大小。
- Dt_Free使用棧來實現釋放二叉搜索樹
- DtListInsert二叉樹插入
首先找到插入位置,再分別判斷是否有左右孩子,分情況分析最后創建結點並插入到對應位置。
- DtListPrint_preOrder前序遍歷
用非遞歸算法來實現,使用棧來實現。
- InOrderTraverse中序遍歷
遞歸算法來實現
- Dt_List_postOrder后序遍歷
遞歸算法來實現
系統測試
1.程序運行界面
2.有序表開始計算
3.無序表開始計算
4.
二叉搜索樹—中序遍歷
5.
二叉搜索樹—前序遍
6.二叉搜索樹—后序遍
7.HASH表
8.搜索功能
9.保存
10.保存文件演示
11.行頁數
12.結果分析
13.運行時間窗口演示
14.源代碼演示窗口
15.幫助選項
源代碼
1 #ifndef FRMMAIN_H 2 #define FRMMAIN_H 3 4 #include <string.h> 5 #include <QDialog> 6 7 8 //函數結果狀態代碼 9 #define TRUE 1 10 #define FALSE 0 11 #define OK 1 12 #define ERROR 0 13 #define OVERFLOW -2 14 15 16 // 線性表的動態分配順序存儲結構 17 #define LIST_INIT_SIZE 100 // 線性表存儲空間的初始分配量 18 #define LISTINCREMENT 10 // 線性表存儲空間的分配增量 19 #define HASH_TABLE_LEN 52 // HASH表長 20 #define PAGE_LINE 26 //每個頁行數 21 22 23 const int MAX_CHARACTER = 50; // 單詞最大長度定為50(TUT.txt文中最長單詞為production-education-researching) 24 25 //行數結構 26 typedef struct row_next{ 27 int row; 28 int page; 29 struct row_next *next; //指向下一個單詞的行數 30 }row_next; 31 32 // 順序存儲結構 33 typedef struct 34 { 35 char word[MAX_CHARACTER]; // 存儲單詞,不超過50個字符 36 int count; // 單詞出現次數 37 row_next *row_head; //行數 38 row_next *row_tail; //指向最后一個 39 } ElemType; 40 typedef struct 41 { 42 ElemType *elem; // 存儲空間基址 43 int length; // 當前長度 44 int listsize; // 當前分配的存儲容量(以sizeof(ElemType)為單位) 45 } SqList; 46 47 48 // 線性存儲結構 49 typedef struct 50 { 51 char word[MAX_CHARACTER]; // 存儲單詞,不超過50個字符 52 int count; // 單詞出現次數 53 row_next *row_head; //行數 54 row_next *row_tail; //尾 55 }DtElemType;//數據類型 56 57 typedef struct DtList 58 { 59 DtElemType elem; //存儲單詞 60 struct DtList *Lchild,*Rchild; //左孩子以及右孩子 61 }DtList; 62 63 64 //HASH表結構 65 typedef struct Link_Node 66 { 67 char word[MAX_CHARACTER]; // 存儲單詞,不超過50個字符 68 int count; //計數 69 row_next *row_head; //行數 70 row_next *row_tail; //尾 71 struct Link_Node *next; 72 }Link_Node; 73 74 //哈希表頭 75 typedef struct Hash_Header 76 { 77 Link_Node *Link_head; 78 }Hash_Header; 79 80 81 typedef struct High_count{ 82 char word[MAX_CHARACTER]; 83 int count; 84 }High_count; 85 86 87 88 class QLineEdit; 89 namespace Ui { 90 class frmMain; 91 } 92 93 class frmMain : public QDialog 94 { 95 Q_OBJECT 96 97 public: 98 explicit frmMain(QWidget *parent = 0); 99 ~frmMain(); 100 int SqListInit ( SqList *L ); 101 int pickword ( FILE *f, char *fword ,int *row); 102 int SqListInsert ( SqList *L, int i, char *fword ); 103 int SqList_insert_disorder(SqList *L,char *fword,int row); 104 int SqListBSearch ( SqList *L, char *sword, int &i ); 105 int SqList_search_disorder(SqList *L, char *sword, int &i); 106 void SqListPrint(SqList *L); 107 108 int DtListSearch(DtList *L, char *e,DtList **i); 109 int DtListInsert (DtList **L,char *fword,int row ); 110 int DtListPrint_preOrder(DtList **L); 111 int Dt_Free(DtList **L); 112 int InOrderTraverse(DtList *L); 113 int Dt_List_postOrder(DtList *L); 114 int DtBiao_Creat(DtList **head); 115 116 int HASH_func(char *word); 117 int hash_List_Search(Link_Node *L,char *fword,Link_Node **p ); 118 int hash_List_Insert (Link_Node **L,char *fword ,int row); 119 void HASH_List_print(Hash_Header *L); 120 121 void High_word(SqList *L); 122 123 124 protected: 125 bool eventFilter(QObject *obj, QEvent *event); 126 void mouseMoveEvent(QMouseEvent *e); 127 void mousePressEvent(QMouseEvent *e); 128 void mouseReleaseEvent(QMouseEvent *); 129 130 private slots: 131 void on_btnMenu_Close_clicked(); 132 133 void on_btnMenu_Max_clicked(); 134 135 void on_btnMenu_Min_clicked(); 136 137 void on_pushButton_clicked(); 138 139 void on_pushButton_2_clicked(); 140 141 void on_pushButton_3_clicked(); 142 143 int OnBtnOpen();//打開文件 144 145 void OnBtnSave();//保存計算結果 146 147 int OnStart();//有序表--開始計算 148 149 int SqList_disorder_start();//無序表--開始計算 150 151 void textFind(); //查找文本 152 153 void findNext(); //查找下一個 154 155 void createPdf();//打印pdf 156 157 void Dt_createPdf();//線性表打印pdf 158 159 void hash_createPdf();//哈希表打印pdf 160 161 int DtBiao_OnStart();//動態表開始計算按鈕 162 163 void clearTbWidget();//清空表格內容 164 165 void Dt_Clear();//動態表表格清空 166 167 void Dt_BtnSave();//動態表保存 168 169 int DtBiao_Onstart_preOrder();//前序遍歷 170 171 int DtBiao_Onstart_PostOrder();//后序遍歷 172 173 int on_Btn_HASH_start();//HASH表開始計算按鈕 174 175 void hash_BtnSave();//HASH表保存 176 177 void hash_Clear();//HASH表內容清空 178 179 180 181 private: 182 Ui::frmMain *ui; 183 184 QPoint mousePoint; 185 bool mousePressed; 186 bool max; 187 QRect location; 188 189 void InitStyle(); 190 191 QLineEdit *lineEdit; 192 193 }; 194 195 #endif // FRMMAIN_H
靜態表
1 //函數結果狀態代碼 2 #define TRUE 1 3 #define FALSE 0 4 #define OK 1 5 #define ERROR 0 6 #define OVERFLOW -2 7 8 9 // 線性表的動態分配順序存儲結構 10 #define LIST_INIT_SIZE 100 // 線性表存儲空間的初始分配量 11 #define LISTINCREMENT 10 // 線性表存儲空間的分配增量 12 #define HASH_TABLE_LEN 52 // HASH表長 13 14 15 const int MAX_CHARACTER = 50; // 單詞最大長度定為50(TUT.txt文中最長單詞為production-education-researching) 16 17 //行數結構 18 typedef struct row_next{ 19 int row; 20 struct row_next *next; //指向下一個單詞的行數 21 }row_next; 22 23 // 順序存儲結構 24 typedef struct 25 { 26 char word[MAX_CHARACTER]; // 存儲單詞,不超過50個字符 27 int count; // 單詞出現次數 28 row_next *row_head; //行數 29 } ElemType; 30 typedef struct 31 { 32 ElemType *elem; // 存儲空間基址 33 int length; // 當前長度 34 int listsize; // 當前分配的存儲容量(以sizeof(ElemType)為單位) 35 } SqList; 36 37 38 /*************************** 39 40 主要功能函數___順序表的實現 41 42 *************************/ 43 44 int frmMain::OnStart() 45 { 46 int j=0,pronum=0; 47 48 /*計算所消耗的時間---開始時間*/ 49 DWORDstart,stop,search_began,search_end,search_time=0,Insert_began,Insert_end,Insert_time=0, order_began,order_end,search_all_Time=0,insert_all_Time=0; 50 51 start = GetTickCount(); 52 53 FILE *f1; 54 FILE* fp=fopen("C:\Qt\src\QUI\linshi.txt","wb"); 55 56 QString str=ui->plainTextEdit->toPlainText(); 57 fprintf(fp,"%s",str.toStdString().c_str()); 58 fclose(fp); 59 60 SqList L; // 建立線性表 61 SqListInit ( &L ); // 初始化順序表 62 63 char fword[MAX_CHARACTER]; // 使用fword數組保存文件中的單詞 64 fword[MAX_CHARACTER - 1] = '\0'; 65 int i = -1; // 設置i為插入位置 66 int row=1; 67 row_next *row_p; 68 f1=fopen("QtsrcQUIlinshi.txt","r"); 69 70 if(f1==NULL) return 0; 71 72 while ( !feof ( f1 ) ) // 讀文件未結束 73 { 74 int judge = pickword ( f1, fword ,&row); // 從f指向的文件中提取單詞到fword中 75 76 if ( -1 == judge ) // 數組越界時提示並退出 77 { 78 printf ( "存在單詞字符長度超過數組界限\n" ); 79 return -1; 80 } 81 82 search_began=GetTickCount(); 83 if ( SqListBSearch ( &L, fword, i ) ) // i返回插入位置或單詞在順序表中位置 84 { 85 search_end=GetTickCount(); 86 87 if(search_time<(search_end-search_began)){ 88 search_time=search_end-search_began; 89 90 } 91 92 search_all_Time=search_all_Time+(search_end-search_began); 93 94 //qDebug() << tr("search:%1 ms").arg(search_time); 95 96 // 在順序表中找到該單詞 97 L.elem[i].count++; // 單詞出現次數加1 98 99 row_p=(row_next *)malloc(sizeof(row_next)); 100 row_p->row=row; 101 row_p->next=L.elem[i].row_head->next; 102 L.elem[i].row_head->next=row_p; 103 } 104 else 105 { 106 Insert_began=GetTickCount(); 107 108 // 順序表中未找到該單詞 109 SqListInsert ( &L, i, fword ); // 在第i個位置上插入 110 L.elem[i].row_head=(row_next *)malloc(sizeof(row_next)); 111 L.elem[i].row_head->row=row; 112 L.elem[i].row_head->next=NULL; 113 114 Insert_end=GetTickCount(); 115 116 if(Insert_time<Insert_end-Insert_began){ 117 Insert_time=Insert_end-Insert_began; 118 } 119 120 insert_all_Time=insert_all_Time+(Insert_end-Insert_began); 121 } 122 123 } 124 125 /****程序運行結束,計算時間並顯示****/ 126 stop = GetTickCount(); 127 //printf("time: %lld ms\n", stop - start); 128 129 QString str1=tr("創建時間: %1 ms").arg(stop - start); 130 ui->TimeLine->setText(str1); 131 str1=tr("折半:%1 ms,最長:%2 ms").arg(search_all_Time).arg(search_time); 132 ui->Sq_search_ltimeline->setText(str1); 133 str1=tr("插入:%1 ms,最長:%2 ms").arg(insert_all_Time).arg(Insert_time); 134 ui->Sq_insert_timeline->setText(str1); 135 136 137 /*****進度條****/ 138 for(i=0;i<=5;i++){ 139 //ui->progressBar->setValue(pronum); 140 //Sleep(1); 141 for(pronum=0;pronum<=100;pronum++){ 142 ui->progressBar->setValue(pronum); 143 //Sleep(1); 144 } 145 } 146 147 // 148 ui->tableWidget->clearContents(); 149 for(j=ui->tableWidget->rowCount();j>=0;j--){ 150 151 ui->tableWidget->removeRow(j); 152 } 153 154 order_began=GetTickCount(); 155 156 // 將結果寫入f2指向的文件中 157 SqListPrint ( &L ); 158 159 order_end=GetTickCount(); 160 161 str1=tr("遍歷時間 : %1 ms").arg(order_end-order_began); 162 ui->Sq_order_line->setText(str1); 163 164 i=0; 165 while(i<ui->tableWidget->rowCount()/3){ 166 QComboBox *comBox = new QComboBox(); 167 while(L.elem[i].row_head){ 168 comBox->addItem(tr("%1").arg(L.elem[i].row_head->row)); 169 L.elem[i].row_head=L.elem[i].row_head->next; 170 } 171 ui->tableWidget->setCellWidget(i,2,comBox); 172 i++; 173 } 174 free(L.elem); 175 L.length=0; 176 L.listsize=0; 177 178 } 179 180 int frmMain::SqList_disorder_start(){ 181 182 int j=0,pronum=0; 183 184 185 /*計算所消耗的時間---開始時間*/ 186 DWORD start, stop,search_began,search_end,search_time=0,Insert_began,Insert_end,Insert_time=0, 187 order_began,order_end,search_all_time=0,insert_all_time=0; 188 189 start = GetTickCount(); 190 191 FILE *f1; 192 FILE* fp=fopen("C:\Qt\src\QUI\linshi3.txt","wb"); 193 194 QString str=ui->plainTextEdit->toPlainText(); 195 fprintf(fp,"%s",str.toStdString().c_str()); 196 fclose(fp); 197 198 SqList L; // 建立線性表 199 SqListInit ( &L ); // 初始化順序表 200 201 char fword[MAX_CHARACTER]; // 使用fword數組保存文件中的單詞 202 fword[MAX_CHARACTER - 1] = '\0'; 203 int i = -1; // 設置i為插入位置 204 int row=1; 205 row_next *row_p; 206 207 f1=fopen("QtsrcQUIlinshi3.txt","r"); 208 209 if(f1==NULL) return 0; 210 211 while ( !feof ( f1 ) ) // 讀文件未結束 212 { 213 int judge = pickword ( f1, fword ,&row); // 從f指向的文件中提取單詞到fword中 214 215 if ( -1 == judge ) // 數組越界時提示並退出 216 { 217 printf ( "存在單詞字符長度超過數組界限\n" ); 218 return -1; 219 } 220 221 search_began=GetTickCount(); 222 if ( SqList_search_disorder ( &L, fword, i ) ) // i返回插入位置或單詞在順序表中位置 223 { 224 search_end=GetTickCount(); 225 226 if(search_time<(search_end-search_began)){ 227 search_time=search_end-search_began; 228 } 229 230 search_all_time=search_all_time+(search_end-search_began); 231 232 //qDebug() << tr("search:%1 ms").arg(search_time); 233 234 // 在順序表中找到該單詞 235 L.elem[i].count++; // 單詞出現次數加1 236 237 // row_p=L.elem[i].row_head; 238 // while(row_p){ 239 // row_p=row_p->next; 240 // } 241 row_p=(row_next *)malloc(sizeof(row_next)); 242 row_p->row=row; 243 row_p->next=L.elem[i].row_head->next; 244 L.elem[i].row_head->next=row_p; 245 } 246 else 247 { 248 Insert_began=GetTickCount(); 249 250 // 順序表中未找到該單詞 251 SqList_insert_disorder ( &L,fword ,row); // 插入 252 253 Insert_end=GetTickCount(); 254 255 if(Insert_time<Insert_end-Insert_began){ 256 Insert_time=Insert_end-Insert_began; 257 } 258 259 insert_all_time=insert_all_time+(Insert_end-Insert_began); 260 } 261 262 } 263 264 /****程序運行結束,計算時間並顯示****/ 265 stop = GetTickCount(); 266 267 268 QString str1=tr("創建時間: %1 ms").arg(stop - start); 269 ui->TimeLine->setText(str1); 270 str1=tr("查找:%1 ms,最長:%2 ms").arg(search_all_time).arg(search_time); 271 ui->Sq_search_ltimeline->setText(str1); 272 str1=tr("插入:%1 ms,最長:%2 ms").arg(insert_all_time).arg(Insert_time); 273 ui->Sq_insert_timeline->setText(str1); 274 275 276 /*****進度條****/ 277 for(i=0;i<=5;i++){ 278 //ui->progressBar->setValue(pronum); 279 //Sleep(1); 280 for(pronum=0;pronum<=100;pronum++){ 281 ui->progressBar->setValue(pronum); 282 //Sleep(1); 283 } 284 } 285 286 // 287 ui->tableWidget->clearContents(); 288 for(j=ui->tableWidget->rowCount();j>=0;j--){ 289 290 ui->tableWidget->removeRow(j); 291 } 292 293 order_began=GetTickCount(); 294 295 // 將結果 296 SqListPrint ( &L ); 297 298 order_end=GetTickCount(); 299 300 str1=tr("遍歷時間 : %1 ms").arg(order_end-order_began); 301 ui->Sq_order_line->setText(str1); 302 303 i=0; 304 while(i<ui->tableWidget->rowCount()/3){ 305 QComboBox *comBox = new QComboBox(); 306 while(L.elem[i].row_head){ 307 comBox->addItem(tr("%1").arg(L.elem[i].row_head->row)); 308 L.elem[i].row_head=L.elem[i].row_head->next; 309 } 310 ui->tableWidget->setCellWidget(i,2,comBox); 311 i++; 312 } 313 314 free(L.elem); 315 L.length=0; 316 L.listsize=0; 317 318 } 319 320 /*********SqList_search_disorder**********/ 321 322 int frmMain::SqList_search_disorder ( SqList *L, char *sword, int &i ) 323 { 324 if ( L->length == 0 ) // 當順序表為空時 325 { 326 i = 0; // i返回單詞插入位置 327 return ERROR; 328 } 329 330 // 順序表不空時,在順序表L中查找元素sword,用i返回其在順序表中的位置 331 int low = 0, high = L->length - 1; 332 333 while ( low <= high ) 334 { 335 if(strcmp ( L->elem[low].word, sword )==0){ 336 i=low; 337 return OK; 338 } 339 else{ 340 low++; 341 } 342 } 343 344 return ERROR; // 順序表中不存在待查元素,函數返回值為0,i返回單詞插入位置 345 } 346 347 /***********SqList_insert_disorder************/ 348 349 // 順序表的插入 350 int frmMain::SqList_insert_disorder( SqList *L,char *fword ,int row) 351 { 352 // 在順序線性表L中第i個位置之前插入新的元素e 353 // i的合法值為1≤i≤L.Length + 1 354 // if ( i < 0 || i > L->length ) 355 // { 356 // //printf ( "i的值不合法!" ); 357 // return ERROR; // i的值不合法 358 // } 359 360 int i=L->length; 361 362 if ( L->length >= L->listsize ) 363 { 364 // 當前存儲空間已滿,增加分配 365 ElemType *newbase = ( ElemType * ) realloc ( L->elem, 366 ( L->listsize + LISTINCREMENT ) * sizeof ( ElemType ) ); 367 368 if ( !newbase ) 369 return OVERFLOW; // 存儲分配失敗 370 371 L->elem = newbase; // 新基址 372 L->listsize += LISTINCREMENT; // 增加存儲容量 373 } 374 375 ElemType *p, *q; 376 q = &L->elem[i]; 377 378 strcpy ( q->word, fword ); // 復制fword中的字符到L->elem[i-1].word中 379 L->elem[i].count = 1; // 設置計數初值為1 380 L->length++; // 表長增1 381 382 L->elem[i].row_head=(row_next *)malloc(sizeof(row_next)); 383 L->elem[i].row_head->row=row; 384 L->elem[i].row_head->next=NULL; 385 386 return OK; 387 } 388 389 390 391 392 /****將結果顯示到界面****/ 393 void frmMain::SqListPrint(SqList *L){ 394 int i=0,j=0; 395 396 row_next *row_p; 397 398 while(i<L->length){ 399 400 ui->tableWidget->insertRow(i); 401 ui->tableWidget->setItem(i,0,new QTableWidgetItem(L->elem[i].word)); 402 ui->tableWidget->setItem(i,1,new QTableWidgetItem(QString("%1").arg(L->elem[i].count))); 403 //ui->tableWidget->setItem(i,2,new QTableWidgetItem(QString("%1").arg(L->elem[i].row_head->row))); 404 //ui->tableWidget->update(i,2,new QTableWidgetItem(QString("%1").arg(L->elem[i].row_head->next->row))); 405 406 i++; 407 } 408 } 409 410 411 // 順序表的插入 412 int frmMain::SqListInsert ( SqList *L, int i, char *fword ) 413 { 414 // 在順序線性表L中第i個位置之前插入新的元素e 415 // i的合法值為1≤i≤L.Length + 1 416 if ( i < 0 || i > L->length ) 417 { 418 //printf ( "i的值不合法!" ); 419 return ERROR; // i的值不合法 420 } 421 422 if ( L->length >= L->listsize ) 423 { 424 // 當前存儲空間已滿,增加分配 425 ElemType *newbase = ( ElemType * ) realloc ( L->elem, 426 ( L->listsize + LISTINCREMENT ) * sizeof ( ElemType ) ); 427 428 if ( !newbase ) 429 return OVERFLOW; // 存儲分配失敗 430 431 L->elem = newbase; // 新基址 432 L->listsize += LISTINCREMENT; // 增加存儲容量 433 } 434 435 ElemType *p, *q; 436 q = &L->elem[i]; 437 438 for ( p = &L->elem[L->length - 1]; p >= q; p-- ) // 插入位置之后元素逐個右移 439 { 440 * ( p + 1 ) = *p; 441 } 442 443 strcpy ( q->word, fword ); // 復制fword中的字符到L->elem[i-1].word中 444 L->elem[i].count = 1; // 設置計數初值為1 445 L->length++; // 表長增1 446 return OK; 447 } 448 449 450 // 順序表二分法查找 451 int frmMain::SqListBSearch ( SqList *L, char *sword, int &i ) 452 { 453 if ( L->length == 0 ) // 當順序表為空時 454 { 455 i = 0; // i返回單詞插入位置 456 return ERROR; 457 } 458 459 // 順序表不空時,在順序表L中查找元素sword,用i返回其在順序表中的位置 460 int low = 0, high = L->length - 1, mid = L->length; 461 462 while ( low <= high ) 463 { 464 mid = ( low + high ) / 2; 465 int k = strcmp ( L->elem[mid].word, sword ); 466 467 if ( k == 0 ) // 待查單詞sword等於中間值,找到待查元素 468 { 469 i = mid; 470 return OK; // 查找成功,函數返回值為1,用i返回所查元素在順序表中的位置 471 } 472 else if ( k > 0 ) // 待查單詞sword小於中間值,繼續在前半區間進行查找 473 { 474 high = mid - 1; 475 i = low; 476 } 477 else // 待查單詞sword大於中間值,繼續在后半區間進行查找 478 { 479 low = mid + 1; 480 i = high + 1; 481 } 482 } 483 484 return ERROR; // 順序表中不存在待查元素,函數返回值為0,i返回單詞插入位置 485 } 486 487 int frmMain::pickword ( FILE *f, char *fword , int *row) // 從f指向的文件中提取單詞到fword中 488 { 489 char ch; // ch儲存待檢測字符 490 491 for ( int j = 0 , flag = 0 ; !feof ( f ) ; ) // 逐個對字符進行檢測,flag用於標記,為0時表示單詞中無字母 492 { 493 if ( j >= MAX_CHARACTER ) // 判斷數組是否越界 494 { 495 return -1; 496 } 497 498 ch = fgetc ( f ); // 獲取字符 499 500 501 if ( ch >= 'A' && ch <= 'Z' ) // 大寫字符轉小寫保存在fword數組中 502 { 503 fword[j++] = ch + 32; 504 flag = 1; 505 } 506 507 if ( ( ch >= 'a' && ch <= 'z' ) ) // 小寫字符保存在fword數組中 508 { 509 fword[j++] = ch; 510 flag = 1; 511 } 512 513 if(ch=='\n') 514 { 515 (*row)++; 516 //return 0; 517 } 518 519 if ( '-' == ch && fword[j - 1] >= 'a' && fword[j - 1] <= 'z' ) // 若單詞中帶連字符,將連字符保存在fword數組中 520 { 521 fword[j++] = ch; 522 } 523 524 525 526 if ( ! ( ( ch >= 'A' && ch <= 'Z' ) || ( ch >= 'a' && ch <= 'z' ) || '-' == ch ) 527 && flag == 1 ) // 過濾單詞中的非字母字符 528 { 529 if ( fword[j - 1] == '-' ) // 排除類似於 a- 的單詞 530 fword[j - 1] = '\0'; 531 532 fword[j] = '\0'; // fword數組以'\0'結尾 533 return 0; 534 } 535 536 537 } 538 } 539 540 541 // 順序表的初始化 542 int frmMain::SqListInit ( SqList *L ) 543 { 544 // 構造一個空的順序表L 545 L->elem = ( ElemType * ) malloc ( LIST_INIT_SIZE * sizeof ( ElemType ) ); 546 547 if ( !L->elem ) return OVERFLOW; // 存儲分配失敗 548 549 L->length = 0; 550 L->listsize = LIST_INIT_SIZE; 551 return OK; 552 }
搜索二叉樹
1 int frmMain::DtBiao_OnStart(){ 2 3 DWORD began,end; 4 5 DtList *L; // 建立線性表 6 L=(DtList*)malloc(sizeof(DtList));//給頭指針分配內存 7 strcpy(L->elem.word," "); 8 L->elem.count=0; 9 L->Lchild=L->Rchild=NULL;//左右孩子初始化 10 11 DtBiao_Creat(&L); //創建二叉樹 12 13 began=GetTickCount(); 14 InOrderTraverse(L); //中序遍歷 15 end=GetTickCount(); 16 17 QString str=tr("中序: %1 ms").arg(end-began); 18 ui->Dt_order_line->setText(str); 19 20 Dt_Free(&L); //釋放內存 21 22 } 23 24 int frmMain::DtBiao_Onstart_preOrder(){ 25 26 DWORD began,end; 27 28 DtList *L; // 建立線性表 29 L=(DtList*)malloc(sizeof(DtList));//給頭指針分配內存 30 strcpy(L->elem.word," "); 31 L->elem.count=0; 32 L->Lchild=L->Rchild=NULL;//左右孩子初始化 33 34 DtBiao_Creat(&L); //創建二叉樹 35 36 began=GetTickCount(); 37 DtListPrint_preOrder(&L); //前序遍歷 38 end=GetTickCount(); 39 40 QString str1=tr("前序: %1 ms").arg(end-began); 41 ui->Dt_order_line->setText(str1); 42 43 Dt_Free(&L); //釋放內存 44 } 45 46 int frmMain::DtBiao_Onstart_PostOrder(){ 47 DWORD began,end; 48 49 DtList *L; // 建立線性表 50 L=(DtList*)malloc(sizeof(DtList));//給頭指針分配內存 51 strcpy(L->elem.word," "); 52 L->elem.count=0; 53 L->Lchild=L->Rchild=NULL;//左右孩子初始化 54 55 DtBiao_Creat(&L); //創建二叉樹 56 57 began=GetTickCount(); 58 Dt_List_postOrder(L); //后序遍歷 59 end=GetTickCount(); 60 61 QString str1=tr("后序: %1 ms").arg(end-began); 62 ui->Dt_order_line->setText(str1); 63 64 Dt_Free(&L); //釋放內存 65 } 66 67 68 /*******二叉搜索樹創建*********/ 69 int frmMain::DtBiao_Creat(DtList **head){ 70 71 DtList *L=*head; 72 73 int j=0,pronum=0,y=0,flag=0; 74 75 /*****tablewidget 表格內容清理******/ 76 ui->DtBiao_tableWidget->clearContents(); 77 for(j=ui->DtBiao_tableWidget->rowCount();j>=0;j--){ 78 79 ui->DtBiao_tableWidget->removeRow(j); 80 } 81 82 83 /*****進度條****/ 84 for(y=0;y<=2;y++){ 85 Sleep(1); 86 for(pronum=0;pronum<=75;pronum++){ 87 ui->progressBar->setValue(pronum); 88 //Sleep(1); 89 } 90 } 91 92 93 /*計算所消耗的時間---*/ 94 DWORD start_create, /*創建哈希表開始時間*/ 95 stop_create, /*創建哈希表結束時間*/ 96 search_began_dt, /*搜索開始時間*/ 97 search_end_dt, /*搜索結束時間*/ 98 search_time_dt=0, /*搜索時間*/ 99 Insert_began_dt, /*插入開始時間*/ 100 Insert_end_dt, /*插入結束時間*/ 101 Insert_time_dt=0, /*插入時間*/ 102 search_all_time=0, /*搜索總時間*/ 103 insert_all_time=0; /*插入總時間*/ 104 105 start_create = GetTickCount(); 106 107 FILE *f1; 108 FILE* fp=fopen("C:\Qt\src\QUI\linshi2.txt","wb"); 109 110 QString str=ui->DtBiao_Plaintext->toPlainText(); 111 fprintf(fp,"%s",str.toStdString().c_str()); //把獲取的內容寫進本地txt文件里面 112 fclose(fp); 113 114 115 116 char fword[MAX_CHARACTER]; // 使用fword數組保存文件中的單詞 117 fword[MAX_CHARACTER - 1] = '\0'; 118 DtList *i = NULL; // 設置i為插入位置 119 int row=1; 120 row_next *row_p; 121 122 123 f1=fopen("QtsrcQUIlinshi2.txt","r"); 124 125 if(f1==NULL) return 0; 126 127 while ( !feof ( f1 ) ) // 讀文件未結束 128 { 129 130 int judge = pickword ( f1, fword ,&row); // 從f指向的文件中提取單詞到fword中 131 132 if(flag==0){ //根結點 133 strcpy(L->elem.word,fword); 134 L->elem.count=1; 135 L->elem.row_head=(row_next *)malloc(sizeof(row_next)); 136 L->elem.row_head->row=row%PAGE_LINE; 137 L->elem.row_head->page=row/PAGE_LINE+1; 138 L->elem.row_head->next=NULL; 139 L->elem.row_tail=L->elem.row_head; 140 flag=1; 141 continue; 142 }else{ 143 if ( -1 == judge ) // 數組越界時提示並退出 144 { 145 printf ( "存在單詞字符長度超過數組界限\n" ); 146 return -1; 147 } 148 149 if( -2 == judge ){ 150 continue; //如果是換行符、文件結束符(-1/255) 151 } 152 153 search_began_dt=GetTickCount(); 154 if ( DtListSearch ( L, fword, &i ) ) // i返回插入位置或單詞在線性表中位置 155 { 156 search_end_dt=GetTickCount(); 157 158 if(search_time_dt<(search_end_dt-search_began_dt)){ 159 search_time_dt=search_end_dt-search_began_dt; //記錄最長時間 160 } 161 162 search_all_time=search_all_time+(search_end_dt-search_began_dt);//記錄總搜索時間 163 164 // 在線性表中找到該單詞 165 i->elem.count++; // 單詞出現次數加1 166 167 row_p=(row_next *)malloc(sizeof(row_next)); //為新單詞的行數頁數分配空間 168 row_p->row=row%PAGE_LINE; //獲取當前總行數,並計算賦值 169 row_p->page=row/PAGE_LINE+1;//頁數 170 row_p->next=NULL; 171 i->elem.row_tail->next=row_p;//添加到尾指針的next 172 i->elem.row_tail=i->elem.row_tail->next;//尾指針指向最后 173 } 174 else 175 { 176 Insert_began_dt=GetTickCount(); 177 // 順序表中未找到該單詞 178 DtListInsert ( &L,fword,row ); // 插入 179 180 Insert_end_dt=GetTickCount(); 181 182 if(Insert_time_dt<(Insert_end_dt-Insert_began_dt)){ 183 Insert_time_dt=Insert_end_dt-Insert_began_dt;//最長插入時間 184 } 185 //插入總時間 186 insert_all_time=insert_all_time+(Insert_end_dt-Insert_began_dt); 187 } 188 189 } 190 191 } 192 193 /****程序運行結束,計算時間並顯示****/ 194 stop_create = GetTickCount(); 195 196 //qDebug() << tr("shijian:%1 ms").arg(stop - start); 197 QString str1=tr("創建時間:%1 ms").arg(stop_create - start_create); 198 ui->DtBiao_TimeLine->setText(str1); 199 str1=tr("搜索:%1 ms,最長:%2 ms").arg(search_all_time).arg(search_time_dt); 200 ui->Dt_search_ltimeline->setText(str1); 201 str1=tr("插入:%1 ms,最長:%2 ms").arg(insert_all_time).arg(Insert_time_dt); 202 ui->Dt_insert_timeline->setText(str1); 203 204 205 /*****進度條****/ 206 for(y=0;y<=1;y++){ 207 Sleep(1); 208 for(pronum=0;pronum<=100;pronum++){ 209 ui->progressBar->setValue(pronum); 210 //Sleep(1); 211 } 212 } 213 214 215 } 216 217 218 219 /**free Destroy*** 220 221 使用棧來實現釋放二叉搜索樹 222 223 *****************/ 224 int frmMain::Dt_Free(DtList **L){ 225 int top = -1; 226 DtList *stack[1000], *p, *q; 227 p = *L; 228 if (p == NULL){ 229 free(*L); 230 return OK; 231 } 232 stack[++top] = *L; 233 while (top>-1) { 234 p = stack[top--]; 235 q = p; 236 if (p->Rchild) //釋放右孩子 237 stack[++top] = p->Rchild; 238 if (p->Lchild) //是放左孩子 239 stack[++top] = p->Lchild; 240 free(q); //釋放頭節點 241 } 242 243 return OK; 244 } 245 246 /*******二叉樹搜索********/ 247 int frmMain::DtListSearch(DtList *T, char *e,DtList **i){ 248 int top = -1; 249 DtList *stack[1000], *p; 250 p = T; 251 if(strcmp(p->elem.word,e)==0){ 252 *i=p; 253 return 1; 254 } 255 //首元素進棧 256 stack[++top] = T; 257 while (top>-1) { 258 p = stack[top--]; 259 if (p->Rchild) { 260 if (strcmp(p->Rchild->elem.word,e) == 0){ 261 *i=p->Rchild; //如果找到了則返回該結點地址 262 return 1; 263 } 264 stack[++top] = p->Rchild;//不一樣則進棧 265 } 266 if (p->Lchild) { 267 if (strcmp(p->Lchild->elem.word,e) == 0){ 268 *i=p->Lchild; ////如果找到了則返回該結點地址 269 return 1; 270 } 271 stack[++top] = p->Lchild;//不一樣則進棧 272 } 273 } 274 //free(stack); 275 return 0; 276 } 277 278 /********二叉樹插入********/ 279 int frmMain::DtListInsert(DtList **L, char *fword,int row){ 280 281 DtList *p=*L,*q; 282 283 while(p){ //首先找到插入位置 284 q=p; 285 if(strcmp(p->elem.word,fword)<0){ 286 287 p=p->Rchild; 288 continue; 289 } 290 if(strcmp(p->elem.word,fword)>0){ 291 p=p->Lchild; 292 continue; 293 } 294 if(strcmp(p->elem.word,fword)==0){ 295 break; 296 } 297 298 } 299 if(q->Lchild){ //如果有左孩子,且右孩子為空 300 if(q->Rchild==NULL){ 301 q->Rchild=(DtList*)malloc(sizeof(DtList)); 302 q->Rchild->Lchild=q->Rchild->Rchild=NULL; 303 strcpy(q->Rchild->elem.word,fword); 304 q->Rchild->elem.count=1; 305 306 q->Rchild->elem.row_head=(row_next *)malloc(sizeof(row_next)); 307 q->Rchild->elem.row_head->row=row%PAGE_LINE; 308 q->Rchild->elem.row_head->page=row/PAGE_LINE+1; 309 q->Rchild->elem.row_head->next=NULL; 310 q->Rchild->elem.row_tail=q->Rchild->elem.row_head; 311 return 1; 312 } 313 } 314 if(q->Rchild){ //如果有右孩子,且左孩子為空 315 if(q->Lchild==NULL){ 316 q->Lchild=(DtList*)malloc(sizeof(DtList)); 317 q->Lchild->Lchild=q->Lchild->Rchild=NULL; 318 strcpy(q->Lchild->elem.word,fword); 319 q->Lchild->elem.count=1; 320 321 q->Lchild->elem.row_head=(row_next *)malloc(sizeof(row_next)); 322 q->Lchild->elem.row_head->row=row%PAGE_LINE; 323 q->Lchild->elem.row_head->page=row/PAGE_LINE+1; 324 q->Lchild->elem.row_head->next=NULL; 325 q->Lchild->elem.row_tail=q->Lchild->elem.row_head; 326 return 1; 327 } 328 } 329 if(q->Lchild==NULL && q->Rchild==NULL){ //如果是葉子結點 330 331 if(strcmp(q->elem.word,fword)<0){ //插入到左孩子 332 q->Rchild=(DtList*)malloc(sizeof(DtList)); 333 q->Rchild->Lchild=q->Rchild->Rchild=NULL; 334 strcpy(q->Rchild->elem.word,fword); 335 q->Rchild->elem.count=1; 336 337 q->Rchild->elem.row_head=(row_next *)malloc(sizeof(row_next)); 338 q->Rchild->elem.row_head->row=row%PAGE_LINE; 339 q->Rchild->elem.row_head->page=row/PAGE_LINE+1; 340 q->Rchild->elem.row_head->next=NULL; 341 q->Rchild->elem.row_tail=q->Rchild->elem.row_head; 342 return 1; 343 } 344 else{ //插入到右孩子 345 q->Lchild=(DtList*)malloc(sizeof(DtList)); 346 q->Lchild->Lchild=q->Lchild->Rchild=NULL; 347 strcpy(q->Lchild->elem.word,fword); 348 q->Lchild->elem.count=1; 349 350 q->Lchild->elem.row_head=(row_next *)malloc(sizeof(row_next)); 351 q->Lchild->elem.row_head->row=row%PAGE_LINE; 352 q->Lchild->elem.row_head->page=row/PAGE_LINE+1; 353 q->Lchild->elem.row_head->next=NULL; 354 q->Lchild->elem.row_tail=q->Lchild->elem.row_head; 355 return 1; 356 } 357 } 358 359 return 0; 360 } 361 362 /*********preOrder********/ 363 int frmMain::DtListPrint_preOrder(DtList **Q){ 364 DtList *stack[1000],*p,*L=*Q; 365 long all_count=0; 366 int top=-1,i=0,HIGH_LENTH=100,j; 367 High_count high_word[HIGH_LENTH],*r,*q; //高頻詞匯數組 368 369 while(i<HIGH_LENTH){ 370 high_word[i].count=0; //初始化 371 i++; 372 } 373 374 i=0; 375 p=L; 376 stack[++top]=L; //首元素進棧 377 378 while (top>-1) { 379 p = stack[top--]; 380 ui->DtBiao_tableWidget->insertRow(i);//插入新行 381 ui->DtBiao_tableWidget->setItem(i,0,new QTableWidgetItem(p->elem.word)); 382 ui->DtBiao_tableWidget->setItem(i,1,new QTableWidgetItem(QString("%1").arg(p->elem.count))); 383 ui->DtBiao_tableWidget->setItem(i,2,new QTableWidgetItem(QString(" ( %1 , %2 )").arg(p->elem.row_head->row).arg(p->elem.row_head->page))); 384 all_count+=p->elem.count;//所有單詞求和 385 386 //如果當前單詞出現次數比高頻詞匯數組的最后一個元素大,則進行插入 387 if(p->elem.count>high_word[HIGH_LENTH-1].count){ 388 j=0; 389 while(j<HIGH_LENTH){ 390 if(p->elem.count>high_word[j].count){ 391 q=&high_word[j]; 392 for ( r = &high_word[HIGH_LENTH-1]; r >= q; r-- ) // 插入位置之后元素逐個右移 393 { 394 * ( r + 1 ) = *r; 395 } 396 high_word[j].count=p->elem.count; 397 strcpy(high_word[j].word,p->elem.word); 398 break; 399 } 400 j++; 401 } 402 403 } 404 // if(i<100){ 405 // QComboBox *comBox = new QComboBox(); 406 // while(p->elem.row_head!=p->elem.row_tail->next){ 407 // comBox->addItem(tr(" ( %1 , %2 )").arg(p->elem.row_head->row).arg(p->elem.row_head->page)); 408 // p->elem.row_head=p->elem.row_head->next; 409 // } 410 // ui->DtBiao_tableWidget->setCellWidget(i,2,comBox); 411 // } 412 i++; 413 if (p->Rchild) 414 stack[++top] = p->Rchild;//右孩子進棧 415 if (p->Lchild) 416 stack[++top] = p->Lchild;//左孩子進棧 417 } 418 ui->DtBiao_tableWidget->setItem(0,5,new QTableWidgetItem(QString("總種類:%1").arg(i))); 419 ui->DtBiao_tableWidget->setItem(1,5,new QTableWidgetItem(QString("總單詞:%1").arg(all_count))); 420 421 i=0; 422 while(i<HIGH_LENTH){//高頻詞匯 423 if(high_word[i].count>1){ 424 ui->DtBiao_tableWidget->setItem(i,3,new QTableWidgetItem(high_word[i].word)); 425 ui->DtBiao_tableWidget->setItem(i,4,new QTableWidgetItem(QString("%1").arg(high_word[i].count))); 426 } 427 i++; 428 } 429 } 430 431 /**********InOrder**********/ 432 int frmMain::InOrderTraverse(DtList *T){ 433 int i=0; 434 435 if(T!=NULL){ 436 InOrderTraverse(T->Rchild); 437 ui->DtBiao_tableWidget->insertRow(i); 438 ui->DtBiao_tableWidget->setItem(i,0,new QTableWidgetItem(T->elem.word)); 439 ui->DtBiao_tableWidget->setItem(i,1,new QTableWidgetItem(QString("%1").arg(T->elem.count))); 440 ui->DtBiao_tableWidget->setItem(i,2,new QTableWidgetItem(QString(" ( %1 , %2 )").arg(T->elem.row_head->row).arg(T->elem.row_head->page))); 441 /* 442 if(i<500){ 443 QComboBox *comBox = new QComboBox(); 444 while(T->elem.row_head){ 445 comBox->addItem(tr("%1").arg(T->elem.row_head->row)); 446 T->elem.row_head=T->elem.row_head->next; 447 } 448 ui->DtBiao_tableWidget->setCellWidget(i,2,comBox); 449 } 450 */ 451 InOrderTraverse(T->Lchild); 452 return OK; 453 } 454 return FALSE; 455 } 456 457 /************postOrder**************/ 458 int frmMain::Dt_List_postOrder(DtList *T){ 459 int i=0; 460 if (T != NULL) { 461 Dt_List_postOrder(T->Lchild); 462 Dt_List_postOrder(T->Rchild); 463 ui->DtBiao_tableWidget->insertRow(i); 464 ui->DtBiao_tableWidget->setItem(i,0,new QTableWidgetItem(T->elem.word)); 465 ui->DtBiao_tableWidget->setItem(i,1,new QTableWidgetItem(QString("%1").arg(T->elem.count))); 466 ui->DtBiao_tableWidget->setItem(i,2,new QTableWidgetItem(QString(" ( %1 , %2 )").arg(T->elem.row_head->row).arg(T->elem.row_head->page))); 467 /* 468 if(i<500){ 469 QComboBox *comBox = new QComboBox(); 470 while(T->elem.row_head){ 471 comBox->addItem(tr("%1").arg(T->elem.row_head->row)); 472 T->elem.row_head=T->elem.row_head->next; 473 } 474 ui->DtBiao_tableWidget->setCellWidget(i,2,comBox); 475 }*/ 476 return OK; 477 } 478 return FALSE; 479 }
HASH表
1 /****************************** 2 3 HASH表實現 4 5 *******************************/ 6 7 8 /***哈希表遍歷****/ 9 void frmMain::HASH_List_print(Hash_Header *L){ 10 11 long all_count=0; 12 int i=0,j=0,HIGH_LENTH=100,w; 13 Link_Node *p=NULL; 14 High_count high_word[HIGH_LENTH],*r,*q; 15 16 while(i<HIGH_LENTH){ 17 high_word[i].count=0; 18 i++; 19 } 20 21 for(i=0;i<HASH_TABLE_LEN;i++){ 22 p=L[i].Link_head;//頭指針 23 while(p){/*當p不為空時*/ 24 ui->HASH_tableWidget->insertRow(j);//給表格添加新行 25 ui->HASH_tableWidget->setItem(j,0,new QTableWidgetItem(p->word)); 26 ui->HASH_tableWidget->setItem(j,1,new QTableWidgetItem(QString("%1").arg(p->count))); 27 ui->HASH_tableWidget->setItem(j,2,new QTableWidgetItem(QString(" ( %1 , %2 )").arg(p->row_head->row).arg(p->row_head->page))); 28 29 all_count+=p->count;//所有單詞求和 30 31 //如果當前單詞出現次數比高頻詞匯數組的最后一個元素大,則進行插入 32 if(p->count>high_word[HIGH_LENTH-1].count){ 33 w=0; 34 while(w<HIGH_LENTH){ 35 if(p->count>high_word[w].count){ 36 q=&high_word[w]; 37 for ( r = &high_word[HIGH_LENTH-1]; r >= q; r-- ) // 插入位置之后元素逐個右移 38 { 39 * ( r + 1 ) = *r; 40 } 41 high_word[w].count=p->count; 42 strcpy(high_word[w].word,p->word); 43 break; 44 } 45 w++; 46 } 47 } 48 49 // if(j<10){ 50 // QComboBox *comBox = new QComboBox(); 51 // while(p->row_head!=p->row_tail->next){ 52 // comBox->addItem(tr(" ( %1 , %2 )").arg(p->row_head->row).arg(p->row_head->page)); 53 // p->row_head=p->row_head->next; 54 // } 55 // ui->HASH_tableWidget->setCellWidget(j,2,comBox); 56 // } 57 58 j++;//給表格添加新行 59 p=p->next; 60 } 61 } 62 63 ui->HASH_tableWidget->setItem(0,5,new QTableWidgetItem(QString("總種類:%1").arg(j))); 64 ui->HASH_tableWidget->setItem(1,5,new QTableWidgetItem(QString("總單詞:%1").arg(all_count))); 65 66 i=0; 67 while(i<HIGH_LENTH){ 68 if(high_word[i].count>1){ 69 ui->HASH_tableWidget->setItem(i,3,new QTableWidgetItem(high_word[i].word)); 70 ui->HASH_tableWidget->setItem(i,4,new QTableWidgetItem(QString("%1").arg(high_word[i].count))); 71 } 72 i++; 73 } 74 75 76 } 77 78 /***計算哈希值*** 79 80 取單詞的第一、二字符,把他們的ASCLL值求和並對表長取余 81 82 ***************/ 83 int frmMain::HASH_func(char *word){ 84 85 int hash=0; 86 87 if(strlen(word)==1){ 88 hash=word[0]%HASH_TABLE_LEN; 89 return hash; 90 }else{ 91 hash=(word[0]+word[1])%HASH_TABLE_LEN; 92 return hash; 93 } 94 95 return -1; 96 } 97 98 /***搜索哈希值對應線性表***/ 99 int frmMain::hash_List_Search(Link_Node *L, char *fword, Link_Node **p){ 100 101 Link_Node *q=L; 102 103 while(q){ 104 if(strcmp(q->word,fword)==0){ 105 *p=q; 106 return 1;//如果找到則返回 107 } 108 q=q->next; 109 } 110 return 0; 111 } 112 113 /****哈希表插入**** 114 115 以后進先出的方式 116 117 ****************/ 118 int frmMain::hash_List_Insert(Link_Node **L, char *fword,int row){ 119 120 Link_Node *p=*L,*q; 121 122 if((*L)==NULL){ 123 *L=(Link_Node*)malloc(sizeof(Link_Node)); 124 (*L)->count=1; 125 (*L)->next=NULL; 126 strcpy((*L)->word,fword); 127 128 (*L)->row_head=(row_next*)malloc(sizeof(row_next)); 129 (*L)->row_head->row=row%PAGE_LINE; 130 (*L)->row_head->page=row/PAGE_LINE+1; 131 (*L)->row_head->next=NULL; 132 (*L)->row_tail=(*L)->row_head; 133 return 1; 134 }else{ 135 136 q=(Link_Node*)malloc(sizeof(Link_Node)); 137 q->count=1; 138 139 q->row_head=(row_next*)malloc(sizeof(row_next)); 140 q->row_head->row=row%PAGE_LINE; 141 q->row_head->page=row/PAGE_LINE+1; 142 q->row_head->next=NULL; 143 q->row_tail=q->row_head; 144 145 q->next=(*L)->next; 146 strcpy(q->word,fword); 147 (*L)->next=q; 148 return 1; 149 } 150 151 return 0; 152 153 } 154 155 int frmMain::on_Btn_HASH_start(){ 156 157 /*計算所消耗的時間---*/ 158 DWORD start_create, /*創建哈希表開始時間*/ 159 stop_create, /*創建哈希表結束時間*/ 160 search_began_dt, /*搜索開始時間*/ 161 search_end_dt, /*搜索結束時間*/ 162 search_time_dt=0, /*搜索時間*/ 163 Insert_began_dt, /*插入開始時間*/ 164 Insert_end_dt, /*插入結束時間*/ 165 Insert_time_dt=0, /*插入時間*/ 166 search_all_time=0,/*搜索總時間*/ 167 insert_all_time=0,/*插入總時間*/ 168 order_began_hash, /*遍歷開始時間*/ 169 order_end_hash; /*遍歷結束時間*/ 170 171 start_create = GetTickCount();//創建哈希表開始計時 172 173 174 Hash_Header L[HASH_TABLE_LEN];//哈希表數組聲明 175 176 int i,j=0,pronum=0,y=0; 177 178 /*哈希表數組初始化*/ 179 for(i=0;i<HASH_TABLE_LEN;i++){ 180 L[i].Link_head=NULL; 181 } 182 183 /*清空表格內容*/ 184 ui->HASH_tableWidget->clearContents(); 185 for(j=ui->HASH_tableWidget->rowCount();j>=0;j--){ 186 187 ui->HASH_tableWidget->removeRow(j); 188 } 189 190 191 /*****進度條****/ 192 for(y=0;y<=2;y++){ 193 //ui->progressBar->setValue(pronum); 194 Sleep(1); 195 for(pronum=0;pronum<=75;pronum++){ 196 ui->progressBar->setValue(pronum); 197 //Sleep(1); 198 } 199 } 200 201 202 FILE *f1; 203 FILE* fp=fopen("C:\Qt\src\QUI\linshi4.txt","wb"); 204 205 QString str=ui->HaSH_Plaintext->toPlainText(); //從plaintext中讀取用戶輸入的數據 206 fprintf(fp,"%s",str.toStdString().c_str()); //把讀取到的文本內容臨時保存到text文件 207 fclose(fp); //關閉文件 208 209 char fword[MAX_CHARACTER]; // 使用fword數組保存文件中的單詞 210 fword[MAX_CHARACTER - 1] = '\0'; //字符串數組最后以'\0'結束 211 Link_Node *p = NULL; // 設置p為在HASH 表中的位置 212 int hash_value=-1; //hash_value 為對應單詞哈希值 213 int row=1; 214 row_next *row_p; 215 216 217 f1=fopen("QtsrcQUIlinshi4.txt","r"); 218 219 if(f1==NULL) return 0; 220 221 while ( !feof ( f1 ) ) // 讀文件未結束 222 { 223 224 int judge = pickword ( f1, fword ,&row); // 從f指向的文件中提取單詞到fword中 225 226 if ( -1 == judge ) // 數組越界時跳過該單詞 227 { 228 continue; 229 } 230 231 if ( -2 == judge ){ 232 continue; 233 } 234 235 hash_value=HASH_func(fword); //計算哈希值 236 237 //qDebug() << tr("hash_value:%1 ms").arg(hash_value); 238 239 if(hash_value==-1) /**無單詞***/ 240 return 0; 241 242 search_began_dt=GetTickCount();/*搜索開始計時*/ 243 244 if ( hash_List_Search ( L[hash_value].Link_head, fword, &p ) ) 245 { 246 search_end_dt=GetTickCount();/*搜索結束計時*/ 247 248 /*記錄最長時間*/ 249 if(search_time_dt<(search_end_dt-search_began_dt)){ 250 search_time_dt=search_end_dt-search_began_dt; 251 } 252 /*記錄總時間*/ 253 search_all_time=search_all_time+(search_end_dt-search_began_dt); 254 255 // 在HASH表中找到該單詞 256 p->count++; // 單詞出現次數加1 257 258 row_p=(row_next*)malloc(sizeof(row_next)); 259 row_p->row=row%PAGE_LINE; 260 row_p->page=row/PAGE_LINE+1; 261 p->row_tail->next=row_p; 262 p->row_tail=p->row_tail->next; 263 } 264 else 265 { 266 /*插入開始計時*/ 267 Insert_began_dt=GetTickCount(); 268 269 // HASH表中未找到該單詞 270 hash_List_Insert ( &(L[hash_value].Link_head),fword,row); // 插入 271 272 /*插入結束計時*/ 273 Insert_end_dt=GetTickCount(); 274 275 /*記錄最長時間*/ 276 if(Insert_time_dt<(Insert_end_dt-Insert_began_dt)){ 277 Insert_time_dt=Insert_end_dt-Insert_began_dt; 278 } 279 280 /*記錄總時間*/ 281 insert_all_time=insert_all_time+(Insert_end_dt-Insert_began_dt); 282 } 283 284 } 285 fclose(f1);//關閉文件 286 287 order_began_hash=GetTickCount();/*遍歷開始計時*/ 288 289 // j=0; 290 // for(i=0;i<HASH_TABLE_LEN;i++){ 291 // p=L[i].Link_head; 292 // while(p){ 293 // ui->HASH_tableWidget->insertRow(j); 294 // ui->HASH_tableWidget->setItem(j,0,new QTableWidgetItem(p->word)); 295 //ui->HASH_tableWidget->setItem(j,1,newQTableWidgetItem(QString("%1").arg(p->count))); 296 //ui->HASH_tableWidget->setItem(j,2,newQTableWidgetItem(QString("( %1 , %2 )").arg(p->row_head->row).arg(p->row_head->page))); 297 // j++; 298 // p=p->next; 299 // } 300 // } 301 302 order_end_hash=GetTickCount();/*遍歷結束計時*/ 303 304 305 /*****進度條****/ 306 for(y=0;y<=1;y++){ 307 Sleep(1); 308 for(pronum=0;pronum<=100;pronum++){ 309 ui->progressBar->setValue(pronum); 310 //Sleep(1); 311 } 312 } 313 314 /****程序運行結束,計算時間並顯示****/ 315 stop_create = GetTickCount(); 316 QString str1=tr("創建時間:%1 ms").arg(stop_create - start_create); 317 ui->HASH_TimeLine->setText(str1); 318 str1=tr("搜索:%1 ms,最長:%2 ms").arg(search_all_time).arg(search_time_dt); 319 ui->hash_search_ltimeline->setText(str1); 320 str1=tr("插入:%1 ms,最長:%2 ms").arg(insert_all_time).arg(Insert_time_dt); 321 ui->hash_insert_timeline->setText(str1); 322 str1=tr("遍歷時間 : %1 ms").arg(order_end_hash-order_began_hash); 323 ui->hash_order_line->setText(str1); 324 325 HASH_List_print(L); 326 /* 327 j=0; 328 for(i=0;i<HASH_TABLE_LEN;i++){ 329 p=L[i].Link_head; 330 while(p){ 331 QComboBox *comBox=new QComboBox; 332 while(p->row_head){ 333 comBox->addItem(tr("%1").arg(p->row_head->row)); 334 p->row_head=p->row_head->next; 335 } 336 ui->HASH_tableWidget->setCellWidget(j,2,comBox); 337 j++; 338 p=p->next; 339 } 340 } 341 */ 342 }
以上是主要的功能源碼,整體源碼需要的請留言。