1. 程式人生 > >【資料結構】5.1 順序表的查詢以及二分查詢的實現

【資料結構】5.1 順序表的查詢以及二分查詢的實現

類的結構如下:

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(); };

類的建構函式,這裡加入了一個標誌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

 

測試結果: