实验4.2 链表合并
要求
- 使用题目 链表实现 中实现的链表类、迭代器类完成本题
- 不得使用与题目实现相关的STL
描述
给定两组整数序列,你需要分别创建两个有序链表,使用链表迭代器实现链表的合并,并分别输出这三个有序链表的索引与元素的异或和。
Note: 给定序列是无序的,你需要首先得到一个有序的链表
格式
输入
第一行两个整数 N 和 M。
第二行 N 个整数,代表第一组整数序列。
第三行 M 个整数,代表第二组整数序列。
输出
三行整数。分别代表第一组数、第二组数对应的有序链表与合并后有序链表的索引与元素的异或和。
链表异或和的计算方式如下:
f ( chain ) = ∑ i = 0 n − 1 i ⊕ chain [ i ] , n = len(chain) f(\text{chain})=\sum_{i=0}^{n-1} i\oplus \text{chain}[i], n=\text{len(chain)} f(chain)=i=0∑n−1i⊕chain[i],n=len(chain)
思路与探讨
线性表链式描述
整体思路描述
-
用名次排序将无序变有序
-
使用链表迭代器实现链表的合并
-
分别输出这三个有序链表的索引与元素的异或和。
细节思路
-
名次排序参考实验2
-
链表类、迭代器类、索引与元素的异或和参考实验4.1
-
链表的合并
combine(chain<T>&L1,chain<T>&L2)
思路-
借助迭代器,实现遍历
iterator current1 = L1.begin(); iterator current2 = L2.begin();
-
情况(1):在合并的过程中,current1已经合并完了,但current2还有。
- 考虑current1为空,直接插入current2 。
-
情况(2):在合并的过程中,current2已经合并完了,但current1还有
- 考虑current2为空,直接插入current1。
-
情况(3):current1和current2都还有,比较大小,先放小的。
- (3.1):current1 的更小先放current1
- (3.2):current2 的更小先放current2
- (3.3):若两个元素相等,则依次插入
-
若已看懂思路,试着自己写~
实现代码
#include<iostream>
using namespace std;
//名次排序(参考实验2,但把assist改为动态数组且将值相等但位置靠后的名次规定为大
template<class T>
void rankSort(T *array,int n)
{
T *new_array = new T [n];//创建附加数组
T *assist = new T [n];//用数组array记录n个元素的名次
for(int i = 0;i < n;i++)
{
assist[i] = 0;
}
for(int i = 1;i < n;i++)
{
for(int j = 0;j < i;j++)
{
if(array[j] <= array[i] ||(j < i && array[j] == array[i]))
assist[i]++;
else
assist[j]++;
}
}
for (int i = 0;i < n;i++)
{
//利用辅助数组,按照名次将array[i]暂时贴到新开辟的new_array[]中
new_array[assist[i]] = array[i];
}
for (int j = 0;j < n;j++)
{
array[j] = new_array[j];//将数组array重新进行赋值操作
}
delete []new_array;
delete []assist;
}
//结构chainNode
template<class T>
struct chainNode
{
//数据成员
T element;
chainNode<T> *next;
//方法
chainNode() {}
chainNode(const T &element)
{
this->element = element;
}
chainNode(const T &element,chainNode<T>*next)
{
this->element = element;
this->next = next;
}
};
//定义链表类
template<class T>
class chain
{
public:
//构造函数
chain()
{
firstNode = NULL;
listSize = 0;
}
//链表的成员类iterator
class iterator
{
public:
//构造函数
iterator(chainNode<T>*theNode = NULL)
{node = theNode;}
//解引用操作符
T& operator*() const {return node->element;}
T* operator->() const {return &node->element;}
//迭代器加法操作
iterator& operator++()
{node = node->next; return *this;}//前加
iterator operator++(int)
{iterator old = *this;node = node->next;return old;}//后加
//相等检验
bool operator != (const iterator right) const
{return node != right.node;}
bool operator == (const iterator right) const
{return node == right.node;}
protected:
chainNode<T>*node;//指向表节点的指针
};
//返回指向线性表首元素的指针
iterator begin() {return iterator(firstNode);}
//返回指向线性表尾节点的下一个位置
iterator end() {return iterator(NULL);}
//在索引theIndex处插入元素theElement
void insert(int theIndex,const T &theElement)
{
//情况(1)在链表头插入
if(theIndex == 0)
firstNode = new chainNode<T>(theElement,firstNode);
//情况(2)在第theIndex>0位置插入
else
{
//找到第theIndex-1个元素的位置p
chainNode<T>*p = firstNode;
for(int i = 0;i < theIndex-1;i++)
p = p->next;
//申请新节点(其元素为theElement,指针为p的后继)
//并让新节点成为p的后继
p->next=new chainNode<T>(theElement,p->next);
}
//listSize加1
listSize++;
}
//计算链表索引与元素的异或和
int sum()
{
int S = 0,index = 0;
iterator beginning = begin();
while(index < listSize)
{
S += index ^ (*beginning);
beginning++;
index++;
}
return S;
}
//将链表赋值为两个链表的有序连接
void combine(chain<T>&L1,chain<T>&L2)
{
iterator current1 = L1.begin();
iterator current2 = L2.begin();
for(int i = 0;i < L1.listSize + L2.listSize;)
{
//情况(1):在合并的过程中,current1已经合并完了,但current2还有
//考虑current1为空,直接插入current2
if(current1 == NULL)
{
insert(i,*current2);
current2++;
i++;
continue;
}
//情况(2):在合并的过程中,current2已经合并完了,但current1还有
//考虑current2为空,直接插入current1
if(current2 == NULL)
{
insert(i,*current1);
current1++;
i++;
continue;
}
//情况(3):current1和current2都还有,比较大小,先放小的
//(3.1):current1 的更小先放这个
if((*current1) < (*current2))
{
insert(i,*current1);
current1++;
i++;
}
//(3.2):current2 的更小先放这个
else if((*current1) > (*current2))
{
insert(i,*current2);
current2++;
i++;
}
//(3.3):若两个元素相等,则依次插入
else
{
insert(i,*current1);
i++;
insert(i,*current2);
current1++;
current2++;
i++;
}
}
}
private:
chainNode<T>*firstNode; //链表的头指针
int listSize; //链表的长度
};
int main()
{
int N,M;
cin >> N >> M;
int *a1 = new int[N];
for(int i = 0;i < N;i++) cin >> a1[i]; //输入Array1的节点元素值
rankSort(a1,N); //使元素有序
chain<int>Array1; //创建链表
for(int i = 0;i < N;i++) Array1.insert(i,a1[i]); //插入各节点
int *a2 = new int[M];
for(int i = 0;i<M;i++) cin >> a2[i]; //输入Array2的节点元素值
rankSort(a2,M); //使元素有序
chain<int>Array2; //创建链表
for(int i = 0;i < M;i++) Array2.insert(i,a2[i]); //插入各节点
chain<int>Array;
Array.combine(Array1,Array2); //将连接结果存入Array
cout << Array1.sum() << endl; //输出Array1的异或和
cout << Array2.sum() << endl; //输出Array2的异或和
cout << Array.sum() << endl; //输出Array的异或和
delete []a1;
delete []a2;
return 0;
}