1. 程式人生 > 其它 >資料結構課程設計_排名估計

資料結構課程設計_排名估計

/*
*本文僅供學習參考使用
**/

一、選題

1、所選題目

  題目五:排名估計

2、選題內容

(1)問題描述

某次考試有n個選手參加,知情人洩露了若干組排序資訊,每組資訊包括兩個人的排中情況,如A>B A<B或者A-B.分別表示A在B之前,A在B之後,A和B排名相等。你的任務是儘量求出完整的排序表。

(2)設計要求

要求一:選手測試資料請自行構造,儲存在文字檔案中。

要求二:一個測試資料檔案可以有多個測試用例。

要求三:需要包含三種測試用例,一是資料不矛盾,但無法完整排

序:二是資料可以完整排序;三是資料有矛盾,如A>B、B>C、 C>A,無法排序。

要求四:選手姓名用逗號分隔,每個姓名可以很長;採用雜湊表索引選手。(可選)

相關資料結構和演算法:

並查集、圖、鄰接表、拓撲排序、雜湊表。

 

 

二、實現分析

1.題目分析與設計方案

  針對題目要求,鑑於c++語言高效的執行速度及強大的標準模板庫STL,我們小組選用c++語言進行本次課程設計。

  題目要求我們將按照題目要求所自行制定的測試資料存入文字檔案(TXT檔案)中,文字中有三類資料資訊:A>B(A排名在B之前),A<B(A排名在B之後),A-B(A與B排名相等),文字中每組資料儲存為一行。

    整體的解答思路就是首先將資料從TXT文字讀入記憶體中,先使用並查集將相等的資料合併為一個集合,選擇一個節點為該集合的代表節點,後續對該集合中所有節點的操作都將轉移到代表節點上,集合中除代表節點外,其餘節點均不再參與後續的構圖等過程,只需在輸出結果時插入到代表節點的前面。然後構造雜湊表和有向圖,雜湊表採用資料項字串的ASCII碼相加然後對雜湊表的最大儲存空間取模,採用線性探測解決雜湊衝突。圖使用鄰接表儲存,圖中節點使用雜湊表作為索引。然後對有向圖進行拓撲排序,當圖有環的時候證明資料是矛盾的,就是出現了A>B, B>C,C>A的情況,這種情況構圖是有環的,拓撲排序完整與否可以判斷是否有環。當拓撲排序時同時有兩個節點入度為0就是無法排序的情況,也就是A>C, B>C,A和B的關係沒有給出所以無法確定A和B的關係,A和B就無法排序,排除這兩種情況,拓撲排序的結果就是最終排序答案

2.輸入輸出說明

輸入:

  程式從工程檔案中直接讀取預置的TXT文字作為程式輸入,我們小組一共預置了三種測試資料,包括可以完整排序樣例1(無排名相等)、可以完整排序樣例2(有排名相等)、資料不矛盾但無法完整排序、資料有矛盾無法排序共四組測試樣例,測試樣例不可增加,但可以在四組樣例中修改測試資料。

輸出:

  程式使用控制檯介面進行結果輸出,使用win32函式封裝了易操作、結果清晰的使用者互動介面,為了避免個別姓名過長或過短造成輸出的冗餘和獲得更加的直觀的程式結果,我們規定測試樣例中不同兩個姓名的首字母不能相同,並在輸出時用首字母代替姓名,程式輸出有三種結果,分別對應三種測試樣例:

  (1) 可以排序:輸出完整的排序情況

  (2) 資料不矛盾但無法排序:輸出資料在哪個節點之後出現了無法排序的情況

  (3) 資料矛盾:輸出資料在哪個節點之後出現了矛盾

3.資料結構使用分析

  程式中主要運用了:並查集、雜湊表、圖、佇列、線性表等資料結構。

  並查集使用陣列(ufs[])表示,如果節點沒有相等節點,則ufs[i] = i, 即它的代表節點就是它本身,如圖2.1中,ufs[4] = 4。如果節點有相等節點,則所有相等節點組成一個集合,若a = b = c,a為其代表節點,則有ufs[c] = ufs[b] = ufs[a] = a, 如圖2.1中, 節點1 = 節點3 = 節點8, 節點1為其代表節點,則有ufs[8] = ufs[3] = ufs[1] = 1,這樣當我們索引節點8時,得到的是其代表節點:節點1,對節點8的所有操作都將在節點1進行。

 

   

 圖2.1 並查集關係

  雜湊表節點HashNode包含兩項屬性:節點儲存的姓名string name和當前節點的狀態enum EntryType Info, 狀態值是一個列舉型別:

1 enum EntryType { Legitimate, Empty, Deleted };

  分別代表當前節點的狀態:已存放數值、空節點、節點已刪除雜湊表資料結構HashTable包含兩項屬性:已經存入的資料大小TableSize和雜湊節點陣列指標HashNode *Cells。

  雜湊表提供了三個訪問介面,分別為:

1 int hash_func(string name);//雜湊函式,返回應插入下標,以姓名的ASCII碼總和作為雜湊索引
2 
3 int hash_insert(HashTable& tab, string name); //雜湊表插入,採用線性探測,返回插入位置的下標
4 
5 int hash_find(HashTable& tab, string name);//雜湊查詢,返回查詢元素下標

  

圖2.2 雜湊表結構

  有向圖節點Tunode包含四項屬性:節點資料name、入度indegree、出度outdegree、節點狀態state,state是一個列舉型別:

1 enum State { Hang, Using, DataContra };
2 
3 /* 節點屬性裡增加的一個狀態:(掛起、使用中, 矛盾),當u v相等時,u代替v所有的操作,
4 
5 |* v的狀態變為:掛起,不再加入圖中參與後面的圖演算法,在輸出結果時,插入到u的前面。
6 
7 |* 矛盾代表資料在該節點出現無法完整排序的情況
8 
9 */

  以節點指標儲存有向圖資訊,vector陣列儲存圖鄰接表資訊,對有向圖節點的訪問使用雜湊表索引進行訪問。

1 Tunode* Ceils;//圖資訊,與鄰接連結串列下標一一對應
2 
3 vector<int> adj[MAXN];//圖鄰接表

  對有向圖提供了拓撲排序介面,拓撲排序返回返回值是一個列舉型別,為了能夠在後續將“掛起”的節點插入到結果中進行輸出,拓撲排序的結果儲存在連結串列RES中:

1 list<int> RES;//用於儲存拓撲排序結果
2 
3 enum TopState { True, Contra, False };//拓撲排序返回的三種狀態,分別代表資料能排序、資料不矛盾但無法排序、資料矛盾
4 
5 enum TopState TopSort();//拓撲排序

圖2.3 有向圖結構

3、演算法設計與分析

(1)演算法正確性分析

  程式中主要使用了拓撲排序演算法,我們主要針對拓撲排序演算法進行分析

圖3.1 拓撲排序演算法

  •初始化:進入拓撲排序後申請輔助空佇列q,選出入度為零的有效節點加入佇列,使用臨時變數count統計加入佇列中的節點數, flag標記資料狀態, cnt統計存入結果連結串列的資料數量,將第一個入度為零的節點加入佇列和結果連結串列中。

     •保持:不斷彈出佇列的隊頂元素,加入到結果連結串列中,並將其鄰接節點加入到佇列中,在判斷鄰接節點時,會使用臨接節點的代表節點,如果資料集是正確的,一定會有且僅有一個節點加入到佇列中,如果是佇列中存在兩個以上元素,證明資料集存在無法排序的節點,將flag標記為Contra,標記有資料無法排序。

  •終止:當佇列為空時,程式終止,根據存入結果連結串列的節點數量和flag的狀態判斷拓撲排序返回值,資料集按出隊順序排列即為資料集的拓撲排序結果,依次儲存在RES結果連結串列中,遍歷RES結果連結串列即為最終答案,因此演算法正確。

(2)複雜度分析

  •時間複雜度:程式中各演算法時間複雜度如圖所示:

圖3.2 各函式時間複雜度

  拓撲排序中e為有向圖中邊的數量,整體的時間複雜度為O(n ),若設計算機單次執行時間為1e-9s,此程式的效能趨勢圖如下:

圖3.3 理論效能趨勢圖

  •空間複雜度:

  拓撲排序演算法額外申請了一個佇列,空間複雜度為O(n)。

  •不同資料結構的效能差異:

  我們可以在程式中取消雜湊表索引而採用直接儲存姓名,這樣可以節省一定的空間,但是代價是每次使用姓名時都會在姓名陣列中查詢並返回所在位置,每次索引都將耗費O(n)的時間,得不償失。

一、實驗結果截圖及分析

1、實驗結果截圖

1選單選擇

四、實驗程式碼

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <fstream>
  4 #include <string>
  5 #include <vector>
  6 #include <queue>
  7 #include <list>
  8 #include "Interface.h"
  9 using namespace std;
 10 
 11 const int MAXN = 100;//最大儲存空間
 12 int ResCnt;//最終加入圖中參與圖演算法資料的數量
 13 enum State { Hang, Using, DataContra };
 14 /* 節點屬性裡增加的一個狀態:(掛起、使用中, 矛盾),當u v相等時,u代替v所有的操作,
 15 |* v的狀態變為:掛起,不再加入圖中參與後面的圖演算法,在輸出結果時,插入到u的前面。
 16 |* 矛盾代表資料在該節點出現無法完整排序的情況
 17 */
 18 struct Tunode {
 19     string name;//節點資料
 20     int indegree;//入度
 21     int outdegree;//出度
 22     enum State state;
 23 };
 24 int ufs[MAXN];//並查集,當u v排名相等時,將u v作為一個集合,所有對v的操作轉移到對u進行操作,即使ufs[v] = u
 25 Tunode* Ceils;//圖資訊,與鄰接連結串列下標一一對應
 26 vector<int> adj[MAXN];//圖鄰接表
 27 
 28 /***********************    TXT檔案讀取    ************************/
 29 vector<string> fileMsg;//用於儲存讀取的檔案資訊
 30 void Read_File(string filename);//讀取檔案內容到fileMsg
 31 
 32 /***********************    拓撲排序    ************************/
 33 list<int> RES;//用於儲存拓撲排序結果
 34 enum TopState { True, Contra, False };//拓撲排序返回的三種狀態,分別代表資料能排序、資料不矛盾但無法排序、資料矛盾
 35 enum TopState TopSort();//拓撲排序
 36 
 37 /***********************    雜湊表    ************************/
 38 enum EntryType { Legitimate, Empty, Deleted };//用於雜湊索引的節點的狀態 已存、空、已刪除
 39 struct HashNode {//雜湊表資料節點
 40     string name;
 41     enum EntryType Info;//用於雜湊索引的狀態值
 42 };
 43 struct HashTable {//雜湊表
 44     int TableSize = 0;//已經存入的資料大小
 45     struct HashNode* Cells; /* 存放節點的陣列 */
 46 };
 47 int hash_func(string name);//雜湊函式,返回應插入下標,以姓名的ASCII碼總和作為雜湊索引
 48 int hash_insert(HashTable& tab, string name); //雜湊表插入,採用線性探測,返回插入位置的下標
 49 int hash_find(HashTable& tab, string name);//雜湊查詢,返回查詢元素下標
 50 HashTable tab;//雜湊表
 51 
 52 /***********************    並查集    ************************
 53 |*ufs_find: 並查集路徑壓縮查詢,返回x所在集合的代表節點*/
 54 int ufs_find(int x) {
 55     if (x == ufs[x])
 56         return x;
 57     else {
 58         ufs[x] = ufs_find(ufs[x]);  //父節點設為根節點
 59         return ufs[x];//返回父節點
 60     }
 61 }
 62 inline void merge(int u, int v) {//並查集,合併,將 v 合併到 u, 簡單來說,即ufs[v] = u, 這樣在使用ufs[v]時,得到的是u
 63     ufs[ufs_find(v)] = ufs_find(u);
 64 }
 65 
 66 /***********************    過程封裝函式    ************************/
 67 void __Init__();//初始化全域性變數, 讀取TXT檔案
 68 void Read_Msg_equal();//讀出排名相等的條目,進行並查集合並
 69 void Read_Msg_unequal();//讀出大小條目,構造圖鄰接表
 70 void PrintRes(enum TopState res);//根據拓撲排序的狀態返回值輸出結果
 71 void __Free__();//釋放記憶體
 72 
 73 int main() {
 74     setTitle("排名估計");//設定控制檯標題
 75     while (1) {//迴圈讀入,非法輸入退出
 76         /***            一、初始化全域性變數, 讀取TXT檔案          ***/
 77         __Init__();
 78 
 79         /***            二、解析fileMsg,構圖           ***
 80         |*解析讀出來的fileMsg,將姓名存入雜湊表便於索引,利用雜湊表的索引構建圖鄰接表
 81         |*使用索引時,會判斷節點有沒有代表節點,
 82         |*    1.先讀出排名相等的條目,進行並查集合並    */
 83         Read_Msg_equal();
 84         /**    2.讀出大小條目,構造圖鄰接表    */
 85         Read_Msg_unequal();
 86 
 87         /***            三、對圖進行拓撲排序           ***/
 88         for (int i = 0; i < MAXN; i++) {
 89             if (Ceils[i].name != "-1" && Ceils[i].state != Hang) {//統計有效資料數量
 90                 ResCnt++;
 91             }
 92         }
 93         enum TopState res = TopSort();//拓撲排序,得到排序結果狀態返回值
 94 
 95         /***            四、輸出結果           ***/
 96         PrintRes(res);//根據拓撲排序的狀態返回值輸出結果
 97         __Free__();//釋放記憶體
 98     }
 99     return 0;
100 }
101 void __Init__() {//初始化函式
102     system("cls");//清屏
103     mainFrame();//主要介面框架
104     ResCnt = 0;
105     tab.Cells = new HashNode[MAXN];
106     Ceils = new Tunode[MAXN];
107     for (int i = 0; i < MAXN; i++) {
108         ufs[i] = i;//並查集初始化,所有節點"各自為戰"
109         Ceils[i].state = Using; Ceils[i].name = "-1"; Ceils[i].indegree = 0; Ceils[i].outdegree = 0;
110         tab.Cells[i].Info = Empty;
111     }
112     string file[4] = { "可以完整排序樣例1(無排名相等).txt", "可以完整排序樣例2(有排名相等) .txt",
113                        "資料不矛盾但無法完整排序.txt",      "資料有矛盾無法排序.txt" };
114     setPos(LEFTOTHER + 25, TOPOTHER + 7);
115     cout << "當前可選擇四個初始化樣例:";
116     for (int i = 1; i <= 4; i++) {
117         setPos(LEFTOTHER + 25, TOPOTHER + 7 + i * 3);
118         cout << i << ". " << file[i - 1];
119     }
120     string tip = "請選擇讀入的檔案:";
121     setPos((WIDTH - tip.size()) / 2 + LEFTOTHER - 1, HIGHT + TOPOTHER - 2);
122     cout << tip;
123     
124     int choise;
125     cin >> choise;
126     if (choise < 1 || choise > 4) {
127         system("cls");//清屏
128         tip = "非法輸入!程式退出";
129         setPos((WIDTH - tip.size()) / 2 + LEFTOTHER, TOPOTHER + 10);//居中列印
130         cout << tip;
131         mainFrame();
132         exit(-1);
133     }
134     Read_File(file[choise - 1]);
135 }
136 void Read_Msg_equal() {//讀出排名相等的條目,進行並查集合並
137     for (int i = 0; i < fileMsg.size(); i++) {//先讀出排名相等的條目,進行並查集合並
138         int pos;
139         if ((pos = fileMsg[i].find("-", 0)) != -1) {//資料集中a-b代表ab排名相等
140             /*    根據符號分割,將姓名分割出來儲存到臨時變數u v中   **/
141 
142             string u = fileMsg[i].substr(0, pos);
143             string v = fileMsg[i].substr(pos + 1, fileMsg[i].size());
144             //查詢雜湊表中是否名字已經存在
145             int u_index = hash_find(tab, u);//u, v 在雜湊表中的索引
146             int v_index = hash_find(tab, v);
147             if (u_index == -1) {//姓名不存在,將姓名插入雜湊表,更新下標
148                 u_index = hash_insert(tab, u);
149                 Ceils[u_index].name = u;
150 
151             }
152             if (v_index == -1) {//姓名不存在,將姓名插入雜湊表,更新下標
153                 v_index = hash_insert(tab, v);
154                 Ceils[v_index].name = v;
155             }
156             /*並查集,將u設為v的代表節點**/
157             merge(u_index, v_index);
158             Ceils[v_index].state = Hang;//v的狀態變更為掛起,將不再參與後續的構圖
159             //cout << Ceils[u_index].name << " = " << Ceils[v_index].name << " /*v的代表 " << Ceils[ufs_find(v_index)].name << endl;
160         }
161     }
162 }
163 void Read_Msg_unequal(){//讀出大小條目,構造圖鄰接表
164     for (int i = 0; i < fileMsg.size(); i++) {
165         int pos;
166         if ((pos = fileMsg[i].find(">", 0)) != -1) {
167             /*    根據符號分割,將姓名分割出來儲存到臨時變數u v中   **/
168             string u = fileMsg[i].substr(0, pos);
169             string v = fileMsg[i].substr(pos + 1, fileMsg[i].size());
170 
171             //查詢雜湊表中是否名字已經存在
172             int u_index = hash_find(tab, u);//u, v 在雜湊表中的索引
173             int v_index = hash_find(tab, v);
174             if (u_index == -1) {//姓名不存在,將姓名插入雜湊表,更新下標
175                 u_index = hash_insert(tab, u);
176                 Ceils[u_index].name = u;
177             }
178             if (v_index == -1) {//姓名不存在,將姓名插入雜湊表,更新下標
179                 v_index = hash_insert(tab, v);
180                 Ceils[v_index].name = v;
181             }
182             adj[ufs_find(u_index)].push_back(ufs_find(v_index)); //u > v 即u 指向v
183             Ceils[ufs_find(u_index)].outdegree++;
184             Ceils[ufs_find(v_index)].indegree++;
185             //cout << Ceils[u_index].name << " > " << Ceils[v_index].name << " /*圖由 " << Ceils[ufs_find(u_index)].name << " 指向 "<< Ceils[ufs_find(v_index)].name << endl;
186         }
187         else if ((pos = fileMsg[i].find("<", 0)) != -1) {
188             /*    根據符號分割,將姓名分割出來儲存到臨時變數u v中   **/
189             string u = fileMsg[i].substr(0, pos);
190             string v = fileMsg[i].substr(pos + 1, fileMsg[i].size());
191 
192             //查詢雜湊表中是否名字已經存在
193             int u_index = hash_find(tab, u);//u, v 在雜湊表中的索引
194             int v_index = hash_find(tab, v);
195             if (u_index == -1) {//姓名不存在,將姓名插入雜湊表,更新下標
196                 u_index = hash_insert(tab, u);
197                 Ceils[u_index].name = u;
198             }
199             if (v_index == -1) {//姓名不存在,將姓名插入雜湊表,更新下標
200                 v_index = hash_insert(tab, v);
201                 Ceils[v_index].name = v;
202             }
203             adj[ufs_find(v_index)].push_back(ufs_find(u_index)); //u < v 即v 指向 u
204             Ceils[ufs_find(u_index)].indegree++;
205             Ceils[ufs_find(v_index)].outdegree++;
206             //cout << Ceils[u_index].name << " < " << Ceils[v_index].name << " /*圖由 " << Ceils[ufs_find(v_index)].name << " 指向 "<< Ceils[ufs_find(u_index)].name << endl;
207         }
208     }
209 }
210 void __Free__() {//釋放記憶體
211     for (int i = 0; i < MAXN; i++) adj[i].clear();//清空圖鄰接表
212     fileMsg.clear();//清空Msg中的元素
213     RES.clear();//清空結果陣列
214     ResCnt = 0;
215     delete [] tab.Cells;
216     delete [] Ceils;
217 }
218 void Read_File(string filename) {
219     fstream input(filename, ios::in);//c++檔案輸入流讀取檔案,ios::in 以讀方式開啟
220     if (!input) {//如果沒有找到檔案,程式終止
221         cout << "沒有找到檔案!" << endl;
222         exit(-1);
223     }
224     string msg;
225     while (getline(input, msg)) {//逐行取存
226         fileMsg.push_back(msg);//存入fileMsg
227     }
228     input.clear();
229 }
230 enum TopState TopSort() {
231     queue<int> q;//用於拓撲排序的輔助佇列
232     int count = 0;//入度為零的節點數,超過2個代表無法排序
233     enum TopState flag = True;//標記資料
234     int cnt = 0;//結果儲存下標
235     for (int i = 0; i < MAXN; i++) {
236         if (Ceils[i].name != "-1" && Ceils[i].state != Hang && Ceils[i].indegree == 0) {//節點有效並且入度為0
237             q.push(i);//加入佇列
238             count++;
239         }
240     }
241     if (count >= 2) flag = Contra;
242     while (!q.empty()) {
243         int t = q.front();
244         q.pop();
245         count--;
246         RES.push_back(t);
247         cnt++;
248         for (int i = 0; i < adj[t].size(); i++) {//尋找新的入度為0的節點,這個節點必然在上一個入度為零節點的鄰接表中
249             int next = ufs_find(adj[t][i]);
250             Ceils[next].indegree--;
251             if (Ceils[next].indegree == 0) {
252                 count++;
253                 q.push(next);
254             }
255         }
256         if (count >= 2) {
257             flag = Contra;
258             Ceils[t].state = DataContra;
259         }
260     }
261     if (cnt == ResCnt && flag == True)
262         return True;
263     else if (cnt == ResCnt && flag == Contra)
264         return Contra;
265     else
266         return False;
267 }
268 void PrintRes(enum TopState res) {//輸出結果
269     system("cls");
270     mainFrame();
271     if (res == True) {
272         string re = "資料可以完整排序, 排序結果為:";
273         setPos((WIDTH - re.size()) / 2 + LEFTOTHER, TOPOTHER + 10);//居中列印
274         cout << re << endl;
275         for (int i = 0; i < MAXN; i++) {//將"掛起"的節點插入到輸出結果列表中,插入位置為其代表節點後方
276             if (Ceils[i].name != "-1" && Ceils[i].state == Hang) {
277                 RES.insert(find(RES.begin(), RES.end(), ufs_find(i)), i);
278             }
279         }
280         re = "";
281         setPos(LEFTOTHER + 14, TOPOTHER + 13);
282         for (list<int>::iterator lt = RES.begin(); lt != RES.end(); lt++) {
283             if (ufs[*lt] != *lt) {
284                 re += Ceils[*lt].name[0];
285                 re += "=";
286             }
287             else {
288                 re += Ceils[*lt].name[0];
289                 re += "->";
290             }  
291         }
292         cout << re.substr(0, re.size() - 2);//-2去掉最後一個箭頭
293         string tip = "按任意鍵繼續...";
294         setPos((WIDTH - tip.size()) / 2 + LEFTOTHER - 1, HIGHT + TOPOTHER - 2);
295         system("pause");
296     }
297     else if (res == Contra) {
298         string re = "資料不矛盾但無法完整排序: ";
299         setPos((WIDTH - re.size()) / 2 + LEFTOTHER, TOPOTHER + 10);//居中列印
300         cout << re;
301         re = "資料在 ";
302         for (list<int>::iterator lt = RES.begin(); lt != RES.end(); lt++) {
303             if (Ceils[*lt].state == DataContra) {
304                 re += Ceils[*lt].name[0];
305                 re += " ";
306             }
307         }
308         re += "後方出現無法排序的情況";
309         setPos((WIDTH - re.size()) / 2 + LEFTOTHER, TOPOTHER + 13);
310         cout << re;
311         string tip = "按任意鍵繼續...";
312         setPos((WIDTH - tip.size()) / 2 + LEFTOTHER - 1, HIGHT + TOPOTHER - 2);
313         system("pause");
314     }
315     else {
316         string re = "資料矛盾無法排序: ";
317         setPos((WIDTH - re.size()) / 2 + LEFTOTHER, TOPOTHER + 10);//居中列印
318         cout << re;
319         re = "資料在 ";
320         re += Ceils[RES.back()].name[0];
321         re += " 後方出現數據矛盾";
322         setPos((WIDTH - re.size()) / 2 + LEFTOTHER, TOPOTHER + 13);
323         cout << re;
324         string tip = "按任意鍵繼續...";
325         setPos((WIDTH - tip.size()) / 2 + LEFTOTHER - 1, HIGHT + TOPOTHER - 2);
326         system("pause");
327     }
328     
329 }
330 int hash_func(string name) {//雜湊函式,返回應插入下標,以姓名的ASCII碼總和作為雜湊索引
331     int char_ascii_sum = 0;
332     for (int i = 0; i < name.size(); i++) {
333         char_ascii_sum += (int)name[i];//累加ASCII碼
334     }
335     return char_ascii_sum % MAXN;
336 }
337 int hash_insert(HashTable& tab, string name) {//雜湊表插入,採用線性探測,返回插入位置的下標
338     int index = hash_func(name);
339     while (tab.Cells[index].Info != Empty) {
340         index++;
341         if (index == MAXN) index = 0;
342     }
343     tab.Cells[index].name = name;
344     tab.Cells[index].Info = Legitimate;
345     tab.TableSize++;
346     return index;
347 }
348 int hash_find(HashTable& tab, string name) {
349     int index = hash_func(name);
350     while (tab.Cells[index].Info == Legitimate) {
351         if (tab.Cells[index].name == name) {
352             return index;
353         }
354         index++;
355         if (index == MAXN) index = 0;
356     }
357     return -1;
358 }
View Code