《数据结构》实验报告
程序名:
一、上机实验的问题和要求:
设计一个程序来实现集合(元素类型为int)的运算,交集、并集二个运算选择一个完成即可,请在自己完成的运算后面打勾:
交集
并集✔
1.生成两个存有集合的单链表,按照元素值递增。
2.通过调用单链表的成员函数来实现集合的运算。每个运算用一个普通函数实现。
二、程序设计的基本思想,原理和算法描述:
(包括程序的结构,数据结构,输入/输出设计,符号名说明等)
使用上次的单链表进行修改,修改插入操作,有序。
先设计一个排序函数将链表进行排序。
再设计一个函数将链表进行合并。
接着设计一个函数将链表中含有相同的元素进行删除。
最后在外面添加一个普通函数Union实现两个集合的并集操作。
Main函数提示用户输入两个集合,输出返回结果。
三、源程序及注释(说明每个文件的文件名即可,电子档的*.h和*.cpp文件压缩传到FTP上):
#pragma once
#pragma once
template<class DataType>
struct Node
{
DataType data;
Node<DataType>* next;
};
template<class DataType>
class LinkList
{
public:
LinkList();
LinkList(DataType a[], int n);
~LinkList();
int Locate(DataType x);
void Insert(int i, DataType x);
DataType Delete(int i);
void PrintList();
//排序链表
Node* sortList(Node* head);
private:
Node<DataType>* first;
};
//合并两个排序的列表
Node<DataType>* mergeTowLists(Node* l1, Node* l2);
//从排序的链表中删除所有重复的元素,以便每一个元素只出现一次
Node<Datatype>* deleteDuplicates(Node* head);
#include<iostream>
using namespace std;
#include "LinkList.h"
template<class DataType>
LinkList<DataType>::LinkList()
{
first = new Node<DataType>;
first->next = NULL;
}
template<class DataType>
LinkList <DataType>::LinkList(DataType a[], int n)
{
Node<DataType>* r, * s;
first = new Node<DataType>;
r = first;
for (int i = 0; i < n; i++)
{
s = new Node<DataType>;
s->data = a[i];
r->next = s;
r = s;
}
r->next = NULL;
}
template <class DataType>
LinkList<DataType> ::~LinkList()
{
Node<DataType>* q = NULL;
while (first != NULL)
{
q = first;
first = first->next;
delete q;
}
}
template<class DataType>
void LinkList<DataType>::Insert(int i, DataType x)
{
Node<DataType>* p = first, * s = NULL;
int count = 0;
while (p != NULL && count < i - 1)
{
p = p->next;
count++;
}
if (p == NULL) throw"位置";
else {
s = new Node<DataType>;
s->data = x;
s->next = p->next;
p->next = s;
}
}
template<class DataType>
DataType LinkList<DataType>::Delete(int i)
{
Node<DataType>* p = first, * q = NULL;
DataType x;
int count = 0;
while (p != NULL && count < i - 1)
{
p = p->next;
count++;
}
if (p == NULL || p->next == NULL)
throw "位置";
else {
q = p->next; x = q->data;
p->next = q->next;
delete q;
return x;
}
}
template <class DataType>
int LinkList<DataType>::Locate(DataType x)
{
Node<DataType>* p = first->next;
int count = 1;
while (p != NULL)
{
if (p->data == x)
return count;
p = p->next;
count++;
}
return 0;
}
template<class DataType>
void LinkList<DataType>::PrintList()
{
//cout << "PrintList start:" << endl;
Node<DataType>* p = first->next;
while (p != NULL)
{
//cout << "PrintList while:" << endl;
cout << p->data << " ";
p = p->next;
}
cout << endl;
}
//合并两个排序的列表 template<class DataType>
Node*mergeTowLists(Node* l1, Node* l2)
{
Node<DataType>* head = new Node<DataType>(-1);
Node<DataType>* p = head;
while (l1 != NULL || l12 != NULL)
{
int val1 = l1 == NULL ? INT_MAX : l1->val;
int val2 = l2 == NULL ? INT_MAX : l2->VaL;
if (val1 <= val2)
{
p->next = l1;
l1 = l1->next;
}
else
{
p->next = l2;
l2 = l2->next;
}
p = p->next;
}
p = head->next;
delete head;
return p;
}
//从排序的链表中删除重复的元素1
//删除所有重复的元素,以便每一个元素只出现一次
template<class DataType>
Node* deleteDuplicates(Node* head)
{
if (head == NULL)return NULL;
Node<DataTrype>* pre = head;
Node<DataType>* p = head->next;
while (p != NULL)
{
if (pre->val == p->val)
{
ListNode* temp = p;
p = p->next;
pre->next = p;
delete temp;
coutinue;
}
pre = pre->next;
}
return head;
}
//排序链表
template<class DataType>
Node* LinkList<DataType>::sortList(Node* head)
{
//首先得到长度length
Node<DataTppe>* p = head;
int len = 0;
while (p != NULL)
{
p = p->next;
len++;
}
Node<DataType>* fakehead = new Node<DataType>(-1);
fakehead->next = head;
for (int interval = 1;interval <= len;interval * 2)
{
Node*<DataType> pre = fakehead;
Node* <DataType>slow = fakehead->next,
* <DataType>fast = fakehead->next;
while (fast != NULL || slow != NULL)
{
int i = 0;
while (i < interval && fast != NULL)
{
fast = fast->next;
i++;
}
int fvisit = 0, svisit = 0;
while (fvisit < interval && svisit < interval && fast != NULL && slow != NULL)
{
if (fast->val < slow->val)
{
pre->next = fast;
pre = fast;
fast = fast->next;
fvisit++;
}
else
{
pre->next = slow;
pre = slow;
slow = slow->next;
svisit++;
}
}
while (fvisit < interval && fast != NULL)
{
pre->next = fast;
pre = fast;
fast = fast->next;
fvisit++;
}
while (svisit < interval && slow != NULL)
{
pre->next = slow;
pre = slow;
slow = slow->next;
svisit++;
}
pre->next = fast;
slow = fast;
}
}
Node* newhead = fakehead->next;
delete fakehead;
return newhead;
}
#include "LinkList.h"
#include "LinkList.cpp"
int main()
{
int a[6] = {1,3,2,4,6,5};
int b[3] = {2,7,4};
LinkList<int>A(a,5);
LinkList<int>B(b, 3);
LinkList<int>C;
cout << "原来A数组为:" << endl;
A.PrintList();
cout << "原来B数组为:" << endl;
B.PrintList();
A.sortList<int>(&A);//排序链表A
B.sortList<int>(&B);//排序链表B
C=mergeTowLists<int>(&A, &B);//合并链表A,B
C.deleteDuplicates<int>(&C);//删除合并后链表中一样的数值
cout << "A,B的并集为:" << endl;
C.PrintList();
}
四、运行输出结果:
(可以将运行结果抓图贴至此处)
五、调试和运行程序过程中产生的问题及采取的措施:
一开始的写出函数其实是很简短的,尤其是排序函数。但后来在我在《编程谜题》这本书看到了链表排序函数发现这上面写的大概是我的两倍,进行对比发现确实是我考虑的条件不够全面,导致给的数据有的时候能实现,有的时候实现不了。这一现象更加证实了我们一开始学习代码所学的一句话,没有办法证明函数是正确的,只能找出bug证明是错误的。
六、对算法的程序的讨论、分析,改进设想,其它经验教训:
一开始的算法十分简单,步骤也很粗略,就写了两步先把集合A中的元素放入集合C再找出B中与A不同的元素按顺序插入进去。但是在实行的过程中实现起来较为困难,比如插在哪里怎么拆进去之类的。于是拆分成了几个更小的函数,虽然步骤好像变多了,要写的函数也多了,但是这样思路会更加清晰。也更容易把问题找出来。
七、对数据结构教学的意见和建议:
数据结构单链表
最新推荐文章于 2022-08-23 22:24:14 发布