【資料結構】5.1 順序表的查詢以及二分查詢的實現
阿新 • • 發佈:2018-12-20
類的結構如下:
class StaticSearchTable { private: int *data; int data_number; bool search_seq(int loc,int key); void select_sort(); bool flag;//區分是否為順序表 public: StaticSearchTable(int n,bool flag); int Search_Seq(int key);//順序查詢 int Search_Bs(int key);//折半查詢(前提是必須是有序表) voidprint(); };
類的建構函式,這裡加入了一個標誌flag用來區分要建立的是順序表還是無序表(有序表即執行一次選擇排序)
StaticSearchTable::StaticSearchTable(int n,bool flag) { this->flag = flag; srand(time(NULL)); //n為陣列元素個數,但是0是不存放數值的故data空間要多開一個 data = new int[n + 1]; for (int i = 0; i < n; i++) { data[i + 1] = rand()%100;//0~99 } data_number = n + 1; if (flag) { select_sort(); } }
二分法查詢:
int StaticSearchTable::Search_Bs(int key) { //設定三個變數low,mid,high儲存陣列的開始中間和末尾的序號 int low = 1; int high = data_number; int result = 0; /*1.如果序號為mid的陣列元素的值與x相等,相當於查詢到了資料,返回mid 2.如果x<a[mid],表示要查詢的資料x位於low與mid-1序號之間 就不需要再去查詢mid與high序號之間的元素了。因此將high變數的值改為mid-1, 重新查詢low與mid-1(即high變數的新值)之間的資料 3.如果x>a[mid],表示要查詢的資料x位於mid+1與high序號之間,就不需要再去查詢low 與mid序號之間的元素了。因此,將low變數的值改為mid+1,重新查詢mid+1(即low變 量的新值)與high之間的資料 4.逐步迴圈,如果到low>high時還未找到目標資料x,則表示陣列中無此資料*/ while (low <= high) { int mid = (low + high) / 2; if (data[mid] == key) { result = mid; break; } else if (key < data[mid]) { high = mid - 1; } else { low = mid + 1; } } return result; }
直接查詢,引入哨兵機制,減少判斷次數:
int StaticSearchTable::Search_Seq(int key) { int i; data[0] = key;//哨兵,判斷是否已經完成整個順序表的遍歷操作 for (i = data_number; !search_seq(i, key); i--);//從後往前查詢 return i;//i若返回0即查詢失敗 }
所有查詢如果失敗都是返回0,在主函式程式碼中加一個判斷即可
下面給出選單設計:
第一層選單
void menu()//模擬選單選項 { cout << " ------------------------------------------------------" << endl; cout << " | 1____________無序順序表查詢 |" << endl; cout << " | 2____________有序順序表查詢 |" << endl; cout << " | 0____________退出系統 |" << endl; cout << " ------------------------------------------------------" << endl; }View Code
第二層選單
void SortedMenu()//有序順序表模擬選單選項 { cout << " ------------------------------------------------------" << endl; cout << " | 1____________有序順序查詢 |" << endl; cout << " | 2____________有序折半查詢 |" << endl; cout << " | 0____________返回 |" << endl; cout << " ------------------------------------------------------" << endl; }View Code
總測試函式(通過switch case 和死迴圈來實現,最後的return 0以及 system(pause)可以刪去,因為按0直接是exit(0))
int main() { while (1) { menu(); int select; cout << "請輸入您的選擇:"; cin >> select; switch (select) { case 1: //無序順序表查詢 { cout << "請輸入無序表中的元素個數:"; int n; cin >> n; StaticSearchTable L(n,false); L.print();//輸出產生的無序表的元素 while (1) { cout << "請輸入待查詢的關鍵字:"; int k; cin >> k; int result = L.Search_Seq(k); if (result > 0) cout << "查詢成功,為第" << result << "個元素." << endl; else cout << "查詢失敗,沒有關鍵字為" << k << "的元素." << endl; char finish; cout << "繼續查詢嗎?(y/n)"; cin >> finish; if (finish == 'n' || finish == 'N') break; } break; } case 2://有序順序表查詢 { cout << "請輸入有序表中的元素個數:"; int n; cin >> n; StaticSearchTable L(n,true); L.print();//輸出產生的有序表的元素 SortedMenu();//有序順序表查詢選項選單 while (1) { int subSelect; cout << "請輸入選擇:"; cin >> subSelect; if (subSelect == 0)//返回上一級 break; int k; cout << "請輸入待查詢的關鍵字:"; cin >> k; int result; if (subSelect == 1) result = L.Search_Seq(k);//有序順序查詢 else if (subSelect == 2) result = L.Search_Bs(k);//折半查詢 else { cout << "選擇錯誤,請重新輸入!" << endl; continue; } if (result > 0) cout << "查詢成功,為第" << result << "個元素." << endl; else cout << "查詢失敗,沒有關鍵字為" << k << "的元素." << endl; } break; } case 0: exit(0); default: cout << "您輸入的選項有誤,請重新輸入:"; } } system("pause"); return 0; }View Code
完整程式碼:
/*設計查詢順序表類,實現順序表(在無序和有序兩種情況) 的順序查詢和折半查詢等操作。*/ #include<iostream> #include<ctime> using namespace std; class StaticSearchTable { private: int *data; int data_number; bool search_seq(int loc,int key); void select_sort(); bool flag;//區分是否為順序表 public: StaticSearchTable(int n,bool flag); int Search_Seq(int key);//順序查詢 int Search_Bs(int key);//折半查詢(前提是必須是有序表) void print(); }; StaticSearchTable::StaticSearchTable(int n,bool flag) { this->flag = flag; srand(time(NULL)); //n為陣列元素個數,但是0是不存放數值的故data空間要多開一個 data = new int[n + 1]; for (int i = 0; i < n; i++) { data[i + 1] = rand()%100;//0~99 } data_number = n + 1; if (flag) { select_sort(); } } bool StaticSearchTable::search_seq(int loc,int key) { if (!data) { exit(1); } return data[loc] == key; } int StaticSearchTable::Search_Seq(int key) { int i; data[0] = key;//哨兵,判斷是否已經完成整個順序表的遍歷操作 for (i = data_number; !search_seq(i, key); i--);//從後往前查詢 return i;//i若返回0即查詢失敗 } int StaticSearchTable::Search_Bs(int key) { //設定三個變數low,mid,high儲存陣列的開始中間和末尾的序號 int low = 1; int high = data_number; int result = 0; /*1.如果序號為mid的陣列元素的值與x相等,相當於查詢到了資料,返回mid 2.如果x<a[mid],表示要查詢的資料x位於low與mid-1序號之間 就不需要再去查詢mid與high序號之間的元素了。因此將high變數的值改為mid-1, 重新查詢low與mid-1(即high變數的新值)之間的資料 3.如果x>a[mid],表示要查詢的資料x位於mid+1與high序號之間,就不需要再去查詢low 與mid序號之間的元素了。因此,將low變數的值改為mid+1,重新查詢mid+1(即low變 量的新值)與high之間的資料 4.逐步迴圈,如果到low>high時還未找到目標資料x,則表示陣列中無此資料*/ while (low <= high) { int mid = (low + high) / 2; if (data[mid] == key) { result = mid; break; } else if (key < data[mid]) { high = mid - 1; } else { low = mid + 1; } } return result; } void StaticSearchTable::select_sort() { for (int i = 1; i < data_number; i++) { for (int j = i + 1; j < data_number; j++) { if (data[i] > data[j]) { int temp = data[j]; data[j] = data[i]; data[i] = temp; } } } flag = true;//是順序表 } void StaticSearchTable::print() { if (flag) { cout << "順序表為: "; } else { cout << "無序表為: "; } for (int i = 1; i < data_number; i++) { cout << data[i] << " "; } cout << endl; } void menu()//模擬選單選項 { cout << " ------------------------------------------------------" << endl; cout << " | 1____________無序順序表查詢 |" << endl; cout << " | 2____________有序順序表查詢 |" << endl; cout << " | 0____________退出系統 |" << endl; cout << " ------------------------------------------------------" << endl; } void SortedMenu()//有序順序表模擬選單選項 { cout << " ------------------------------------------------------" << endl; cout << " | 1____________有序順序查詢 |" << endl; cout << " | 2____________有序折半查詢 |" << endl; cout << " | 0____________返回 |" << endl; cout << " ------------------------------------------------------" << endl; } int main() { while (1) { menu(); int select; cout << "請輸入您的選擇:"; cin >> select; switch (select) { case 1: //無序順序表查詢 { cout << "請輸入無序表中的元素個數:"; int n; cin >> n; StaticSearchTable L(n,false); L.print();//輸出產生的無序表的元素 while (1) { cout << "請輸入待查詢的關鍵字:"; int k; cin >> k; int result = L.Search_Seq(k); if (result > 0) cout << "查詢成功,為第" << result << "個元素." << endl; else cout << "查詢失敗,沒有關鍵字為" << k << "的元素." << endl; char finish; cout << "繼續查詢嗎?(y/n)"; cin >> finish; if (finish == 'n' || finish == 'N') break; } break; } case 2://有序順序表查詢 { cout << "請輸入有序表中的元素個數:"; int n; cin >> n; StaticSearchTable L(n,true); L.print();//輸出產生的有序表的元素 SortedMenu();//有序順序表查詢選項選單 while (1) { int subSelect; cout << "請輸入選擇:"; cin >> subSelect; if (subSelect == 0)//返回上一級 break; int k; cout << "請輸入待查詢的關鍵字:"; cin >> k; int result; if (subSelect == 1) result = L.Search_Seq(k);//有序順序查詢 else if (subSelect == 2) result = L.Search_Bs(k);//折半查詢 else { cout << "選擇錯誤,請重新輸入!" << endl; continue; } if (result > 0) cout << "查詢成功,為第" << result << "個元素." << endl; else cout << "查詢失敗,沒有關鍵字為" << k << "的元素." << endl; } break; } case 0: exit(0); default: cout << "您輸入的選項有誤,請重新輸入:"; } } system("pause"); return 0; }View Code
測試結果: