实验一:线性表的基本操作实现及其应用

一、实验目的

1 熟练掌握线性表的结构特点,掌握顺序表的基本操作。

2 巩固 C++相关的程序设计方法与技术。

3 学会使用顺序表解决实际问题。

二、实验内容

1、顺序表的建立与操作实现

建立个元素的顺序表(的大小和表里数据自己确定),实现相关的操作:输出,插入,删除,查找等功能。编写完整程序实现,程序语言不限定,使用技术形式不定。

2、实际问题的解决(*)

使用顺序表来实现约瑟夫环问题。

三、设计与编码

1.本实验用到的理论知识
(1)线性表的序号用数组的下标i表示,注意对线性表操作时其下标要在范围之内
(2)建造线性表或在线性表中入元素时线性表的长度不能超过数组的最大度。
2.算法设计

(1)定义SeqList类模板

class SeqList

{

public:

 

SeqList(){length=0;}                  //建立一个空表

 

        SeqList(int a[], int n);           //带参构造函数

 

        ~SeqList(){}                        //析构函数

 

       void Insert (int i, int x);        //在第i个位置插入值为x的元素

 

       int Delete (int i);                //删除线性表中的第i个元素

 

       int Locate (int x);                //按值查找,在线性表中查找x的元素序号

 

       int Get (int i);                   //按位查找,在线性表中查找第i个元素

 

       void PrintList();                 //遍历操作,按序号依次输出各元素

 

       int getLength(){return length;}  //获取线性表的长度

 

private:

 

       int data[MaxSize];

 

       int length;                    //线性表长度

};

 

2构造函数:无参构造函数建立一个空表,并给length赋值0;带参构造函数建立一个长度为n的顺序表a[],把length赋值为n,并把数组元素作为顺序表的元素传入顺序表中。
(3)获取线性表的长度:成员函数返回length的值。
(4)按值查找元素序号:①.定义一个布尔类型的变量b,开始赋值false,若有找到元素值为x,b赋值true,若b的值为false,表示没有找到。
②.遍历顺序表,如果元素值为x,输出该元素序号。
(5)按位置查找元素:查找顺序表的第i个元素只需返回类中数组下标为(i-1)的元素,注意查找位置要在顺序表序号范围内,否则抛出异常。
(6)插入元素:若表满了或元素插入位置不在范围之内则抛出异常。插入时,将最后一个元素到第i个元素依次往后移一个位置,再把x插入第i个位置;最后顺序表的长度加1。
(7)删除元素:若表是空表或删除元素位置不在范围之内则抛出异常。删除时把第i+1个元素到最后一个元素依次往前移一个位置,最后线性表的长度-1。
(8)遍历顺序表:依次打印线性表的数据元素

3. 代码:

 

//#ifndef SeqList_H

 

//#define SeqList_H

 

#include<iostream.h>

 

const int MaxSize=10;

 

class SeqList

{

public:

 

SeqList(){length=0;}                  //建立一个空表

 

        SeqList(int a[], int n);           //带参构造函数

 

        ~SeqList(){}                        //析构函数

 

       void Insert (int i, int x);        //在第i个位置插入值为x的元素

 

       int Delete (int i);                //删除线性表中的第i个元素

 

       int Locate (int x);                //按值查找,在线性表中查找x的元素序号

 

       int Get (int i);                   //按位查找,在线性表中查找第i个元素

 

       void PrintList();                 //遍历操作,按序号依次输出各元素

 

       int getLength(){return length;}  //获取线性表的长度

 

private:

 

       int data[MaxSize];

 

       int length;                    //线性表长度

};

 

//#endif

 

 

#include<iostream.h>

 

//#include "SeqList.h"

 

SeqList::SeqList(int a[],int n)        //带参构造函数,建一个长度为n的顺序表

{

       if(n>MaxSize)throw"参数非法\n";

 

       for(int i=0;i<n;i++)

 

            data[i]=a[i];

 

       length=n;

}

 

void SeqList::Insert(int i,int x)    //在第i个位置插入值为x的元素

{

       if(length>=MaxSize)throw"上溢\n";

 

       if(i<1||i>length+1)throw"\t\t位置非法\n";

 

       for(int j=length;j>=i;j--)

 

              data[j]=data[j-1];

 

       data[i-1]=x;

 

       length++;

}

 

int SeqList::Delete(int i)            //删除线性表中的第i个元素

{

       if(length==0)throw"\n\t\t下溢\n";

 

       if(i<1||i>length)throw"\n\t\t位置非法\n";

 

       int x=data[i-1];

 

       for(int j=i;j<length;j++)

 

              data[j-1]=data[j];

 

       length--;

 

       return x;

}

 

int SeqList::Locate(int x)           //按值查找

{

       for(int i=0;i<length;i++)

 

              if(data[i]==x)return i+1;

 

              return 0;

}

 

int SeqList::Get(int i)              //按位查找

{

     if(i<1&&i>length)throw"查找位置非法";

 

          else return data[i-1];

}

 

void SeqList::PrintList()            //遍历操作,按序号依次输出各元素

{

       cout<<"\t\t序号\t出列的编号\n";

 

       for(int i=0;i<length;i++)

 

              cout<<"\t\t  "<<i+1<<"\t  "<<data[i]<<"\n";

 

       cout<<"此时线性表的长度是:"<<i<<endl;       //输出此时线性表的长度

}

 

 

#include <iostream.h>

 

//#include "SeqList.h"

 

void main()

{

       int r[5]={1,2,3,4,5};

 

       SeqList L(r,5);

 

       cout<<"执行插入操作前数据:"<<endl;

 

       L.PrintList();

 

       try

       {

              L.Insert(2,3);

       }

 

       catch(char*s)

       {

              cout<<s<<endl;

       }

 

       cout<<"执行插入操作后数据:"<<endl;

 

       L.PrintList();

 

       cout<<"值为3的元素位置为:";

 

       cout<<L.Locate(3)<<endl;

 

   cout<<"1个元素为:";

 

       cout<<L.Get(1)<<endl;

 

       cout<<"执行删除第一个元素操作,删除前数据为:"<<endl;

 

       L.PrintList();

 

       try

       {

              L.Delete(1);

       }

 

       catch(char*s)

       {

              cout<<s<<endl;

       }

 

       cout<<"删除后数据为:"<<endl;

 

       L.PrintList();

}

四、运行与测试

(1)用数组r[5]={1,2,3,4,5};作为线性表的数据元素建立一个顺序表;查找第1个元素,结果是1;查找值为3的元素序号有2;在顺序表的第2个位置插入元素3,遍历顺序表插入成功;删除顺序表的第1个位置的元素,删除成功。
(2)若在建立顺序表时把给定数组的长度5改为15(MaxSize=10),输出异常(参数非法!);
(3)若查找第8个元素,输出异常(查找位置非法!);
(4)若在第0或第8个位置插入元素,输出异常(查找位置非法!);
(5)若删除第0或第8个位置的元素,输出异常(查找位置非法!);

 

五、总结与心得

    通过这次实验复习了C++的大部分知识,但是代码的熟练程度有提高。

疑问:1.求线性表长度这个成员函数在哪里调用?

    2.try{}catch{};抛出异常函数还没学,不太懂。

 

 

 

 

 

 

 

 

2、实际问题的解决(*)

使用顺序表来实现约瑟夫环问题。

c语言:

#include <stdio.h>

#define N 19

#define M 6

 

int main()

{

    

    int players[N];// 所有人组成一个数组

    

    int i = 0, j = 0, alive = N, n = 0;// 初始化变量

    for (; i < N; i++) {

       

        players[i] = 1; // 存活用 1 表示,出局就是 0

    }

 

   

    while (alive > 1) { // 只要不止一人存活,就循环下去

        

        if (j >= N) {// 如果下标越界了,取余数,让其还是在数组下标范围内

            j = j % N;

        }

 

        // 忽略出局的人

        if (players[j] == 1) {

            // 计算现在是第几个人了

            n++;

            

            if (n % M == 0) {// 如果这个人正好是倍数,进行出局处理

               

                players[j] = 0; // 设置这个人出局

                

                --alive;// 存活人数 - 1

            }

        }

        j++;

    }

 

   

    for (i = 0; i < N; i++) { // 输出结果

        if (players[i] == 1) {

            printf("最后存活的人是:%d\n", i + 1);

            break;

        }

    }

 

    return 0;

}

顺序表:

 

#include<iostream.h>

 

const int MaxSize=70;

 

template<class S>

 

class SeqList{

 

private:

 

 S data[MaxSize];

 

 int length;    //线性表的长度

 

public:

 

 SeqList(){length=0;}  //建一个空表

 

 SeqList(int n);

 

 ~SeqList(){}

 

 void Insert(int i,S x);   //在第i个位置插入值为x的元素

 

 int Delete(int i);        //删除线性表中的第i个元素

  

 S Get(int i);            //按序号查找第i个元素

 

 void Locate(S x);       //按值查找元素序号

 

 int GetLength(){return length;}  //获取线性表的长度

 

 void PrintList();               //遍历操作,按序号依次输出各元素

 

};

 

template<class S>

 

 SeqList<S>::SeqList(int n){  //带参构造函数,建一个长度为n的顺序表

 

 if(n>MaxSize) throw"参数非法!\n";

 

 for(int i=0;i<n;i++) data[i]=i+1;

 

 length=n;

}

template<class S>

 

void SeqList<S>::Insert(int i,S x){   //在第i个位置插入值为x的元素

 

 if(length>=MaxSize) throw"上溢!\n";

 

 if(i<1||i>length+1) throw"\t\t插入位置非法!\n";

 

 for(int j=length;j>=i;j--){

 

  data[j]=data[j-1];

 

 }

 data[i-1]=x;

 

 length++;

 

}

template<class S>

 

int SeqList<S>::Delete(int i){    //删除线性表中的第i个元素

 

 if(length==0) throw"\n\t\t下溢!\n";

 

 if(i<1||i>length) throw"\n\t\t查找位置非法!\n";

 

 int x=data[i-1];

 

 for(int j=i;j<length;j++){

 

  data[j-1]=data[j];

 

 }

 length--;

 

 return x;

 

}

template<class S>

 

void SeqList<S>::PrintList(){    //遍历操作,按序号依次输出各元素

 

 cout<<"\t\t序号\t出列的编号\n";

 

 for(int i=0;i<length;i++){

 

  cout<<"\t\t  "<<i+1<<"\t  "<<data[i]<<"\n";

 

 }

 cout<<"此时线性表的长度为:"<<i<<endl;   //输出此时线性表的长度

 

}

int main(){

 

 try{

 

  int n,m,j,k=5,N;

 

  cout<<"请输入玩游戏的人数:";

  

  cin>>n;

 

  SeqList<int> s1(n);       //n个人的编号按顺序存放到s1的顺序表中

 

  cout<<"请输入开始报数的编号:";

  

  cin>>m;

 

  if(m<1||m>s1.GetLength())

  

  throw"\t\t报数编号非法!\n";

 

  cout<<"请输入要出列的编号:";

 

  cin>>j;                //报到k这个数的人(编号)出列

 

  SeqList<int> s2;      //建立顺序表s2

 

  for(int i=0;s1.GetLength()>1;i++){

      N=k;              //计算报数的总次数

  if(k>=n)          //超出下标的最大值,则取kn的余数

  k=k%n;

  if(N%j==0)        //如果是出列编号j的倍数,则该数出列

  s2.Insert(i+1,k);

  m=k;            

  s1.Delete(k);     //删除第k个元素

  k=k+m+1;         //进行第二次报数

  }

  s2.PrintList();                //输出出列的编号

 }

 catch(char *p)

 {

  cout<<p;

 }

 return 0;

}


疑问:顺序表的操作思路跟c语言的一样,为什么运行时总是出现“查找位置非法”?(而且我查找过没出现“ if(i<1||i>length) throw"\n\t\t查找位置非法!\n";”这种状况,求解答)

  • 5
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值