【数据结构】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

 

测试结果:

posted @ 2018-12-20 11:33  巴塞罗那的余晖  阅读(1893)  评论(0编辑  收藏  举报
//雪花飘落效果