实验2.2 单链表实现学生成绩管理

来源:互联网 发布:linux是否安装oracle 编辑:程序博客网 时间:2024/04/28 20:02

实验2.2  单链表实现学生成绩管理


一.实验目的
     巩固线性表的数据结构的存储方法和相关操作,学会针对具体应用,使用线性表的相关知识来解决具体问题。
 
二.实验内容
     建立一个由n个学生成绩的顺序表,n的大小由自己确定,每一个学生的成绩信息由自己确定,实现数据的对表进行插入、删除、查找等操作。分别输出结果。
要求如下:用单链表来实现。


三.相关算法及操作
1、将线性表的抽象数据类型定义在单链表存储结构下用C++中的类实现。由于线性表的数据元素类型不确定,所以采用C++的模板机制。
  
2、构造函数:
  无参构造函数LinkList(),即生成只有结点的空链表,算法如下:
template            LinkList::LinkList()      //无参构造函数LinkList(){         first = new Node;     //生成头结点    first->next=NULL;               //头结点的指针域置空}     

   
  有参构造函数LinkList(DataType a[],int n),即生成一个有n个结点的单链表,采用尾插法的构造方法。
  算法如下:
template  LinkList::LinkList(DataType a[],int n)  //尾插法建立单链表LinkList{  Node   *r,*s;  first = new Node;         //初始化一个空链表r = first;  for(int i=0;i;  s->data=a[i];                       //为每个数组元素建立一个结点r->next =s;  r=s;  }  r->next= NULL;  }  

3、析构函数:将单链表中结点(包括头结点)的存储空间释放。
  算法如下:
template  LinkList::~LinkList()     //单链表析构函数算法~LinkList{  Node *q = NULL;  while(first != NULL)                //释放单链表的每一个结点的存储空间{  q = first;                          //暂存被释放结点first= first->next;                 //first指向被释放结点的下一个结点delete q;  }  }

4、插入操作:在主函数定义插入的学生成绩和位置,输出结果则在定义的位置插入相应的学生成绩。
  ①工作指针p初始化;
  ②查找第i-1个结点并使工作指针p指向该结点
  ③若查找不成功,说明插入位置不合理,抛出插入位置异常;否则,
   a.生成一个元素值为x的新结点s;
   b.将新结点s插入到结点p之后。  

5、查找操作
①按位查找:当工作指针p指向某结点时判断是否为第i个结点,若是,则查找成功;否则,将工作指针p后移。对每个结点依次执行上述操作,直到p为NULL时查找失败;
②按值查找:对单链表中的元素依次进行比较,如果查找成功,返回元素的符号,如果查找不成功,返回0表示查找失败。算法如下:
template  int LinkList::Locate(DataType x)  //单链表按值查找算法{  Node*p =first->next;  int count =1;  while(p!=NULL)  {  if(p->data==x) return count;        //查找成功,结束函数并返回序号p=p->next;  count++;    }  return 0;                           //退出循环表明查找失败}  

6、删除操作:将单链表的第i个结点删去。
  ①工作指针p初始化;累加器count初始化;
  ②查找第i-1个结点并使工作指针p指向该结点;
  ③若p不存在或p的后继结点不存在,则抛出位置异常,否则,
   a.暂存被删结点和被删元素值;
   b.摘链,将结点p的后继结点从链表上摘下;
   c.释放被删结点;
   d.返回被删元素值。
算法如下:
template  DataType LinkList::Delete(int i)  //单链表删除算法{  Node *p =first,*q=NULL;  DataType x;  int count = 0;  while(p!=NULL && countnext;  count++;  }  if(p==NULL ||p->next==NULL) throw"位置";  //结点p不存在或p的后继结点不存在else  {  q=p->next;  x=q->data;                          //暂存被删结点p->next=q->next;                    //摘链return x;  }  }

7、输出:将经过插入、删除操作之后的学生成绩输出


四.相关代码

#include         using namespace std;        template    struct Node       {         DataType data;      Node* next;    };               template     class LinkList     {    public:          LinkList ();                    //无参构造函数,建立只有头结点的空链表    LinkList(DataType a[],int n);   //有参构造函数,建立有n个元素的单链表        ~LinkList();                    //析构函数    void Insert (int i,DataType x); //插入操作     int Locate(DataType x) ;        //按值查找    DataType Delete(int i);         //删除操作    void PrintList();               //遍历操作private:      Node* first;          //单链表的头指针    };               template            LinkList::LinkList()      //无参构造函数LinkList(){         first = new Node;     //生成头结点    first->next=NULL;               //头结点的指针域置空}       template  LinkList::LinkList(DataType a[],int n)  //尾插法建立单链表LinkList{  Node   *r,*s;  first = new Node;         //初始化一个空链表r = first;  for(int i=0;i;  s->data=a[i];                       //为每个数组元素建立一个结点r->next =s;  r=s;  }  r->next= NULL;  }    template  LinkList::~LinkList()     //单链表析构函数算法~LinkList{  Node *q = NULL;  while(first != NULL)                //释放单链表的每一个结点的存储空间{  q = first;                          //暂存被释放结点first= first->next;                 //first指向被释放结点的下一个结点delete q;  }  }  template  void LinkList::Insert(int i,DataType x)  //单链表插入算法{  Node *p = first,*s=NULL;  int count = 0;  while(p!=NULL&&count< i-1)          //查找第i-1个结点{  p = p->next;                        //工作指针p后移count++;  }  if(p==NULL) throw "位置非法";       //没有找到第i-1个结点else  {  s = new Node;  s->data =x;  s->next=p->next;  p->next= s;  }  }    template  DataType LinkList::Delete(int i)  //单链表删除算法{  Node *p =first,*q=NULL;  DataType x;  int count = 0;  while(p!=NULL && countnext;  count++;  }  if(p==NULL ||p->next==NULL) throw"位置";  //结点p不存在或p的后继结点不存在else  {  q=p->next;  x=q->data;                          //暂存被删结点p->next=q->next;                    //摘链return x;  }  }    template  int LinkList::Locate(DataType x)  //单链表按值查找算法{  Node*p =first->next;  int count =1;  while(p!=NULL)  {  if(p->data==x) return count;        //查找成功,结束函数并返回序号p=p->next;  count++;    }  return 0;                           //退出循环表明查找失败}    template  void LinkList::PrintList()  //单链表遍历算法PrintList{  Node*p =first-> next;       //工作指针p初始化while(p!=NULL)  {  cout<data<<" ";  p=p->next;                            //工作指针p后移}  cout< L(score, 5);      cout << "插入前的学生成绩为:" << endl;      L.PrintList();      try      {          L.Insert(6, 100);      }      catch (char *s)      {          cout << s << endl;      }      cout << "插入后的学生成绩为:" << endl;      L.PrintList();  cout <>x;loc=L.Locate(x);cout<<"该成绩所在的位置为:"<


五、调试结果

1、在学生成绩为“50 60 70 80 90”的最后一位插入成绩为“100”的学生



2、显示插入学生成绩的所在位置



3、执行删除第一个学生成绩的操作前后,显示的学生数据



4、当输入查找的元素“88”时,无法找到它的位置,所以显示为“0”



5、当输入查找的学生成绩为“100”时,显示其位置为“6”



6、主页面如下:


七、实验总结与心得体会

      顺序表是静态存储分配。这就从根本上导致了它具有以下缺点:

1、插入和删除操作需移动大量元素;

2、表的容量难以确定;

3、造成存储空间的“碎片”。

     而单链表与之不同的有操作上的区别,它在增删上面有优势,比顺序表效率高。

综合上述所言,顺序表和单链表各有各的优缺点,使用哪一种会好一些要结合具体的问题而言,不能一概而论。 
比如: 
在查询操作使用的比较频繁时,使用顺序表会好一些;在插入、删除操作使用的比较频繁时,使用单链表会好一些。

心得体会:

     第二个实验做完,感觉脑子要烧掉了。这次的实验花费时间比较长,主要是因为对相关的知识还没有熟悉并牢牢掌握,还是要多练习练习。

不过尝试用单链表来实现后,就会发现它跟顺序表的一些区别,还有这两种方式的一些优缺点,这也是收获的一个地方。同时也让我对单链表的知识更加熟悉了,“熟能生巧”,多练习几遍就会很容易上手的了。

    纯青依旧很棒!