DHU数据结构-顺序表- ADT应用-前m个元素后置

目录

1.题目

2.题解

3.代码实现

4.改进


1.题目

                顺序表ADT模板设计及简单应用:将顺序表中前 m 个元素和后 n 个元素进行互换

                                作者: 冯向阳时间限制:  1S章节: DS:线性表

问题描述 :

目的:使用自行设计的顺序表ADT或STL中的vector模板,设计并实现顺序表应用场合的一些简单算法设计。

应用1:试设计一个算法,用尽可能少的辅助空间将非空顺序表中前 m 个元素和后 n 个元素进行互换,即将线性表(a1,a2,…,am,b1,b2,…,bn) 改变成(b1,b2,…,bn,a1,a2,…,am)。假定m始终是有效值。

参考函数原型:

(1)顺序表ADT版本

template<class ElemType>

void Exchange( SqList<ElemType> &A, int m ); // 本算法实现顺序表中前 m 个元素和后 n 个元素的互换

(2)vector版本

template<class ElemType>
void Exchange( vector<ElemType> &A, int m );// 本算法实现顺序表中前 m 个元素和后 n 个元素的互换

输入说明 :

第一行:顺序表的数据元素类型标记(0:int;1:double;2:char;3:string;其余值:输出err)

第二行:待处理顺序表的数据元素(数据元素之间以空格分隔)

第三行:逆置位置m

输出说明 :

第一行:逆置前顺序表的遍历结果(数据元素之间以“,”分隔)

空行

第三行:逆置后顺序表的遍历结果(数据元素之间以“,”分隔)

输入范例 :

0
13 5 27 9 32 123 76 98 54 87
5

输出范例 :

13,5,27,9,32,123,76,98,54,87

123,76,98,54,87,13,5,27,9,32


2.题解

  • 读题:题目要求通过vector或者手写adt来实现顺序表,在此基础上完成一个交换元素的算法
  • 实现顺序表:手写adt还挺麻烦的哈(等有时间再去实现),所以本大懒人选择现成的vector。表的数据的录入还挺麻烦的,不同数据类型录入的方法都不同(把输入部分储存为string类型然后再去转换类型。int考虑字符串转数字,double除了转数字外还有小数,string读入不读空格。而且还要考虑正负)。还有记得考虑空表问题,别把'/0'这个元素插到vector里面然后出错。
  • 实现交换算法:这个容易,只需要进行三步翻转。1.把表中的所有元素翻转  2.把上一步之后的表中后面的m个元素翻转 3.最后把前面n-m个翻转就ok。当然也可以直接枚举一个一个放到对应的位置,但是题目要求少用空间。

3.代码实现

  • 数据录入构成表:
    先用string来存储接下来要录入的元素
            int n;
            string s;
            cin>>n;
            getchars();
            getline(cin,s);
    
    
    
    下面是不同数据类型的录入方法
    
    //int型数据的录入(没有考虑负数情况,也没有考虑空表)
            vector<int> a;
            int num=0;
            for(int i=0; i<s.size(); i++)//遍历输入的string
            {
                if(s[i]==' ')//每当遇到空格时就把前一个数字元素num插入到vector中
                {
                    a.push_back(num);//插入
                    num=0;//数字num刷新归零,以便下一次使用
                }
                else//每当遇到非空格就计算该num的值(实现string转换为int)
                {
                    num=num*10+s[i]-'0';//num位权+1后再加上当前字符的数值
                }
            }
            a.push_back(num);//用于插入最后一个元素。因为最后一个元素后面没有空格,还没有把最后一个元素插入vector就跳出循环了,所以在循环外面把最后一个元素插入
    
    
    
    //double型数据录入(没有考虑负数情况,也没有考虑空表)
            vector<double> b;
            double num=0;
            int flag=0,t=0;//flag为1表示在计算小数部分数值,t表示小数点后的数字长度
            for(int i=0; i<s.size(); i++)
            {
                if(s[i]==' ')
                {
                    num=num/pow(10,t);
                    b.push_back(num);
                    t=0,num=0,flag=0;//刷新归零
                }
                else if(s[i]=='.')
                {
                    flag=1;
                }
                else
                {
                    num=num*10+s[i]-'0';
                    if(flag==1)
                        t++;
                }
            }
            num=num/pow(10,t);
            b.push_back(num);
    
    
    //char型数据录入
            vector<char> c;
            for(int i=0; i<s.size(); i++)
            {
                if(s[i]!=' ')
                    c.push_back(s[i]);
            }
    
    
    //string型数据录入(没有考虑空表)
            vector<string> d;
            string str;
            str.clear();
            for(int i=0; i<s.size(); i++)
            {
                if(s[i]==' ')
                {
                    d.push_back(str);
                    str.clear();
                }
                else
                    str+=s[i];
            }
            d.push_back(str);

  • 模版算法部分:
    //print函数
    template<class T>
    void print(vector<T> &A)
    {
        //法一:用迭代器遍历
        typename::vector<T> ::iterator it;//注意迭代器定义的语句
        for(it=A.begin();it!=A.end();it++)
        {
            if(it==A.begin())cout<<(*it);
            else cout<<","<<(*it);
        }
        cout<<endl;
    
    
        //法二:用长度遍历
        int i;
        for(i=0; i<A.size()-1; i++)
            cout<<A[i]<<",";
        cout<<A[i]<<endl;
        
    }
    
    
    //交换算法,reverse函数要algorithm头文件
    template<class T>
    void change(vector<T> &A)
    {
        print(A);
        cout<<endl;
        int n=A.size()-m;
        reverse(A.begin(),A.end());
        reverse(A.begin(),A.begin()+n);
        reverse(A.begin()+n,A.end());
        print(A);
    }
    

  • 完整代码

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    
    using namespace std;
    int n,m;
    string s;
    
    template<class T>
    void print(vector<T> &A)
    {
        int i;
        for(i=0;i<A.size()-1;i++) cout<<A[i]<<",";
        cout<<A[i]<<endl;
    }
    
    template<class T>
    void change(vector<T> &A)
    {
        print(A);
        cout<<endl;
        int n=A.size()-m;
        reverse(A.begin(),A.end());
        reverse(A.begin(),A.begin()+n);
        reverse(A.begin()+n,A.end());
        print(A);
    }
    
    
    
    int main()
    {
        cin>>n;
        getchar();
        getline(cin,s);
        cin>>m;
    
            if(n==0)
            {
                vector<int> a;
                int num=0;
                for(int i=0;i<s.size();i++)
                {
                    if(s[i]==' ')
                    {
                        a.push_back(num);
                        num=0;
                    }
                    else
                    {
                        num=num*10+s[i]-'0';
                    }
                }
                a.push_back(num);
                change(a);
            }
            else if(n==1)
            {
                vector<double> b;
                double num=0;
                int flag=0,t=0;
                for(int i=0;i<s.size();i++)
                {
                    if(s[i]==' ')
                    {
                        num=num/pow(10,t);
                        b.push_back(num);
                        t=0,num=0,flag=0;
                    }
                    else if(s[i]=='.')
                    {
                        flag=1;
                    }
                    else
                    {
                        num=num*10+s[i]-'0';
                        if(flag==1)t++;
                    }
                }
                num=num/pow(10,t);
                b.push_back(num);
                change(b);
            }
            else if(n==2)
            {
                vector<char> c;
                for(int i=0;i<s.size();i++)
                {
                    if(s[i]!=' ')c.push_back(s[i]);
                }
                change(c);
            }
            else if(n==3)
            {
                vector<string> d;
                string str;
                str.clear();
                for(int i=0;i<s.size();i++)
                {
                    if(s[i]==' ')
                    {
                        d.push_back(str);
                        str.clear();
                    }
                    else str+=s[i];
                }
                d.push_back(str);
                change(d);
            }
            else cout<<"err"<<endl;
    
        return 0;
    }
    


4.改进

在课堂听完老师的讲解之后发现有两处可以进行优化或者钻研

  • 首先是造表,可以用stringstream实现函数模版实现代码复用,并且不需要讨论不同类型数据的录入,方便得很
  • 第二是不能说是优化,只是想尝试手写一个模版类,毕竟老师说从底层理解vector是怎么实现的也更能熟练掌握vector运用嘛,我觉得他说得很对。

以下是代码

  • stringstream使用
    //模版造表函数,在主函数中运用就不需要写这么长的代码,stringstream头文件sstream
    template<class T>
    void CreatList(stringstream &in,vector<T> &sqlist)
    {
        T tmp;
        while(in>>tmp)
            sqlist.push_back(tmp);
    }
    
    
    //以int类型为例
    int main()
    {
        cin>>n;
        cin.ignore();
        getline(cin,s);
        stringstream input(s);
        
        if(n==0)
        {
            vector<int> a;
            CreatList(input,a);
            change(a);
    }

    使用stringstream的完整代码,并且进行代码赏析

    #include <iostream>
    #include <sstream>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    
    using namespace std;
    
    int n,m;
    string s;
    
    template<class T>
    void print(vector<T> &A)
    {
        typename std::vector<T>::iterator it=A.begin();
        for(it;it!=A.end()-1;it++) cout<<*it<<",";
        cout<<*it<<endl;
    }
    
    template<class T>
    void change(stringstream &input,vector<T> &A)
    {
        T str;//用来临时储存单个数据
        while(input>>str) //“stringstream对象 + >>“就是提取字符串中单个数据
            A.push_back(str);//每每提取到单个数据就插入到vector中
    
        print(A);
        cout<<endl;
    
        int x=A.size()-m;
        reverse(A.begin(),A.end());//翻转是用swap实现的,而swap只需要另外开辟一个额外空间,也就是说整个这个操作只多使用了一个空间,因此符合题目要求
        reverse(A.begin(),A.begin()+x);
        reverse(A.begin()+x,A.end());
    
        print(A);
    }
    int main()
    {
        cin>>n;
        getchar();//也可以用cin.ignore()都是用来消除上一个n的输入后保存在缓冲区的回车
        getline(cin,s);//读入string一般用这个读入,不用cin是为了防止碰到string中的空格就读入结束
        stringstream input(s);//创建一个stringstream对象input,并把s的数据存入这个流对象input,因为stringstream对象可以进行单个字符串提取的操作,这么做是方便了提取单个数据来造表
        cin>>m;
    
        if(n!=0&&n!=1&&n!=2&&n!=3) cout<<"err"<<endl;
        else if(n==0)
        {
            vector<int> a;
            change(input,a);
        }
        else if(n==1)
        {
            vector<double> b;
            change(input,b);
        }
        else if(n==2)
        {
            vector<char> c;
            change(input,c);
        }
        else
        {
            vector<string> d;
            change(input,d);
        }
    
        return 0;
    }
    

  • 手写adt

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值