zoukankan      html  css  js  c++  java
  • 【数据结构】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

    测试结果:

  • 相关阅读:
    通过编程添加Outlook联系人和通讯组
    一个比较完整的WindowsFormsApplication实现
    读书笔记:《粘住:为什么我们记住了这些,忘掉了那些?》
    最新购书
    新买的2本书都不错
    压榨机器,Hack,设计极限强度的网络应用
    方向越来越明确了
    思想上激进,行为上保守
    一种遗失了很久的感觉正在慢慢回归
    物极必反,滥用闭包的结果就是回归结构化编程
  • 原文地址:https://www.cnblogs.com/robotpaul/p/10148374.html
Copyright © 2011-2022 走看看