实验4.2 链表合并

该文描述了一个使用链表实现的编程问题,涉及将两个无序整数序列通过名次排序变为有序,然后使用链表迭代器合并这两个有序链表。同时,计算每个链表元素与索引的异或和。文章提供了详细的思路和步骤,包括名次排序、链表合并以及异或和的计算方法。
摘要由CSDN通过智能技术生成

实验4.2 链表合并

要求

  1. 使用题目 链表实现 中实现的链表类、迭代器类完成本题
  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=0n1ichain[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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啦啦右一

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值