实验一 线性表的有关操作
实验学时 2学时
背景知识:顺序表、链表的插入、删除及应用。
目的要求:
(1)掌握线性表的基本运算在两种存储结构(顺序结构和链式结构)上的实现;
(2)掌握线性表的各种操作(建立、插入、删除等)的实现算法;
实验内容:
1.随机产生或键盘输入一组元素,建立一个带头结点的单向链表(无序)。
2.遍历单向链表。
3.把单向链表中元素逆置(不允许申请新的结点空间)。
4.在单向链表中删除所有的偶数元素结点。
5.编写在非递减有序链表中插入一个元素使链表元素仍有序的函数,并利用该函数建立一个非递减有序单向链表。
6.利用算法5建立两个非递减有序单向链表,然后合并成一个非递增链表。
7.利用算法5建立两个非递减有序单向链表,然后合并成一个非递减链表。
8.利用算法1建立的链表,实现将其分解成两个链表,其中一个全部为奇数,另一个全部为偶数(尽量利用已知的存储空间)。
* 9.采用单向链表实现一元多项式的存储并实现两个多项式相加并输出结果。
10.在主函数中设计一个简单的菜单,分别调试上述算法。
*11.综合训练:利用链表实现一个班级学生信息管理(数据录入、插入、删除、排序、查找等,并能够实现将数据存储到文件中)
实验说明
1.算法1至算法7可以以头文件的方式存储,主函数实现该头文件的包含即可调用
2.存储定义
#define MAXSIZE 100 //表中元素的最大个数
typedef int ElemType;//元素类型
typedef struct list{
ElemType elem[MAXSIZE];//静态线性表
int length; //表的实际长度
}SqList;//顺序表的类型名
3.建立顺序表时可利用随机函数自动产生数据。
实验说明
1.类型定义
#include <stdio.h>
typedef int ElemType;//元素类型
typedef struct LNode
{ElemType data;
struct LNode *next;
}LNode,*LinkList;
2.为了算法实现简单,最好采用带头结点的单向链表。
注意问题
1.重点理解链式存储的特点及指针的含义。
2.注意比较顺序存储与链式存储的各自特点。
3.注意比较带头结点、无头结点链表实现插入、删除算法时的区别。
4.单向链表的操作是数据结构的基础,一定要注意对这部分的常见算法的理解。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
using namespace std;
typedef int ElemType;
typedef struct Node
{
ElemType data;
struct Node *next;
} Node, *LinkList;
LinkList CreateList(LinkList &h)
{
LinkList p,q;
ElemType x;
h = (LinkList)malloc(sizeof(Node));
p = h;
while(cin>>x&&x)
{
q = (LinkList)malloc(sizeof(Node));
q->data = x;
p->next = q;
p = q;
}
p->next = NULL;
return h;
}
void Display(LinkList l)
{
LinkList p ;
p = l->next;
while(p!=NULL)
{
cout<<p->data<<" ";
p = p->next;
}
cout<<endl;
}
void Reverse(LinkList &l)
{
LinkList p,q;
p = l->next;
l->next = NULL;
while(p!=NULL)
{
q = p;
p = p->next;
q->next = l->next;
l->next = q;
}
}
void Del_Ou(LinkList &l)
{
LinkList p;
p = l->next;
int i=1;
while(p->next!=NULL)
{
i++;
if(i%2)
p=p->next;
else
{
LinkList q = p->next;
p->next = p->next->next;
free(q);
}
}
}
void Insert(LinkList &l,ElemType x)
{
LinkList p,q;
p = l->next;
while(p->next!=NULL)
{
if(p->next->data<x)
{
p = p->next;
}
else
{
//cout<<x<<endl;
q = new Node;
q->data = x;
q->next = p->next;
p->next = q;
break;
}
}
}
LinkList MergeList(LinkList &h,LinkList &l,LinkList &A)
{
LinkList p,q,r;
p = h->next;
q = l->next;
A = r = h;//init
while(p!=NULL&&q!=NULL)
{
if(p->data <= q->data)
{
r->next = p;
r = p;
p = p->next;
}
else
{
r->next = q;
r = q;
q = q->next;
}
}
r->next = p?p:q;
delete l;
return A;
}
void TakeApart(LinkList &h)
{
LinkList L1,L2;
LinkList p;
p = h->next;
//L1 = h;
//L2 = h;
L1->next = NULL;
L2->next = NULL;
while(p!=NULL)
{
cout<<p->data;
if(p->data%2==1)
{
L1->data = p->data;
L1 = L1->next;
}
else
{
L2->data = p->data;
L2 = L2->next;
}
p = p->next;
}
L1->next = NULL;
L2->next = NULL;
Display(L1);
Display(L2);
}
void DisCreate(LinkList &A)
{
//将表A中结点按序号的奇偶性分解到表A或表B中
int i=0; //i记录表A中结点的序号
LinkList B= (LinkList) malloc (sizeof (Node) ); //创建 B 表表头
B->next=NULL; //B 表的初始化
Node *ra = A, *rb=B; //ra和rb将分别指向将创建的A表和B表的尾结点
LinkList p=A->next; //p为链表工作指针,指向待分解的结点
A->next=NULL; //置空新的 A 表
while (p!=NULL)
{
i++; //序号加 1
if (i%2==0) //处理序号为偶数的链表结点
{
rb->next=p; // 若B表尾描入新结点
rb=p; //rb指向新的尾结点
}
else //处理原序号为奇数的结点
{
ra->next=p; //在A表尾插入新结点
ra=p;
}
p=p->next; //将p恢复为指向新的待处理结点
} //while 结束
ra->next=NULL;
rb->next=NULL;
//return B;
Display(A);
Display(B);
}
int main()
{
// 1 2 3 4 5 6 7 8 9 10 0
LinkList head;
CreateList(head);//建立链表
Display(head);//遍历链表
//Reverse(head);//反转链表
//Display(head);
//Del_Ou(head);//删除偶数下标元素
//Display(head);
//int x;
//cin>>x;//要插入的数
//Insert(head,x);//插入元素,并为非递减序列
//Display(head);
//建立两个非递减有序单向链表,然后合并成一个非递减链表。
//LinkList list2;
//CreateList(list2);//建立链表二
//Display(head);
//Display(list2);
//LinkList AfterMerge;
//Display(MergeList(head,list2,AfterMerge));
//利用算法1建立的链表,实现将其分解成两个链表,
//其中一个全部为奇数,另一个全部为偶数(尽量利用已知的存储空间)。
//TakeApart(head);
//Display(DisCreate(head));
//Display(head);
DisCreate(head);
return 0;
}