您的位置:首页 > 其它

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

2017-10-08 21:15 295 查看
实验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、造成存储空间的“碎片”。

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

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

心得体会:

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

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

    纯青依旧很棒!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: