C++深度理解复杂链表的构造复制

#include <iostream>
using namespace std;
#define Default -1
struct Node
{
    int data;
    Node *next;
    Node *other;//这是复杂链表的额外的一个指针,指向一个指定位置的节点。
    Node(int d = int()) :data(d), next(NULL), other(NULL){}
};

class ContexList
{
public:
    ContexList() :first(NULL)
    {}
    void InsertNext(int a[], int n)
    {
        int i = 0;
        Node *p = NULL;
        for (; i < n; i++)
        {
            Node *s = new Node(a[i]);
            if (first == NULL)
            {
                first = s;
                p = s;
            }
            else
            {
                s->next = p->next;
                p->next = s;
                p = s;
            }
        }
        p = first;
        Node *q = NULL;
        while (p != NULL)
        {
            if (p->next != NULL)
            {
                q = p->next->next;
                p->other = q;
                //每次隔两个指针就用other指针连接一次。
                //构造复杂链表的连接。
            }
            p = p->next;
        }
    }
    void Printf()//打印链表。
    {
        Node *p = first;
        while (p != NULL)
        {
            if (p->other != NULL)
            {
                cout << p->data << "->other:" << p->other->data << endl;
            }
            else
            {
                cout << p->data << "->other:" << "NULL" << endl;
                //打印other的值。
            }
            p = p->next;
        }
    }
    friend void Copy(ContexList cl1, ContexList &cl2)
    {

        Node *oldptr = cl1.first;
        if (oldptr == NULL)return;
        Node *newptr = cl2.first;
        Node *p = newptr;
        Node *m = NULL;

        //好吧,为了防止后面连接重复且混乱的问题,我选择
        //先进行拷贝然后再赋值,为啥要这么做呢?这么做的条理
        //更加的清楚,我考虑过从后面往前拷贝,这样不行,因为
        //这不是数组,无法立刻确定前一个位置的值,如果从前面
        //往后的过程并且赋值的话,会导致重复拷贝,拷贝多次的
        //情况。
        while (oldptr != NULL)
        {
            m = oldptr->next;
            Node *s1 = new Node();
            s1->next = m;
            oldptr->next = s1;

            oldptr = m;
        }

        //赋值并且将other指向确定起来。
        oldptr = cl1.first;
        while (oldptr != NULL)
        {
            m = oldptr->next;
            if (oldptr->other != NULL)
                m->other = oldptr->other->next;
            m->data = oldptr->data;
            oldptr = m->next;
        }

        //这里是正真的拆分重组,将cl1链表链表里面
        //复制的一部分节点摘取出来,然后连接到cl2.first
        //中,实现了拆分以及重组,又不影响以前的链表cl1,
        //又创造了一个新的拷贝与原来链表的链表。
        oldptr = cl1.first;
        Node *q = NULL;
        while (oldptr != NULL)
        {
            m = oldptr->next->next;
            q = m;
            if (p == NULL)
            {
                p = oldptr->next;
                newptr = p;
                cl2.first = newptr;
            }
            else
            {
                p->next = oldptr->next;
                p = p->next;
            }
            oldptr->next = m;
            oldptr = m;
        }
    }
private:

    Node *first;

};

int main()
{
    int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    ContexList cl1;
    cl1.InsertNext(a, sizeof(a) / sizeof(int));

    ContexList cl2;
    Copy(cl1, cl2);
    cout << "链表1->cl1:" << endl;
    cl1.Printf();
    cout << "拷贝之后的链表2->cl2:" << endl;
    cl2.Printf();

    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-25 09:49:32

C++深度理解复杂链表的构造复制的相关文章

RRDtool深度理解

RRDtool深入学习 介绍 RRDtool:Round Robin Database Tool(轮询的数据库工具) 是一种存储数据的方式,使用固定大小的空间来存储数据,并有一个指针指向最新的数据的位置.我们可以把用于存储数据的数据库的空间看成一个圆,上面有很多刻度.这些刻度所在的位置就代表用于存储数据的地方.所谓指针,可以认为是从圆心指向这些刻度的一条直线.指针会随着数据的读写自动移动.要注意的是,这个圆没有起点和终点,所以指针可以一直移动,而不用担心到达终点后就无法前进的问题.在一段时间后,

深度理解依赖注入

1.依赖在哪里   老马举了一个小例子,是开发一个电影列举器(MovieList),这个电影列举器需要使用一个电影查找器(MovieFinder)提供的服务,伪码如下: 1/*服务的接口*/ 2public interface MovieFinder { 3    ArrayList findAll(); 4} 5 6/*服务的消费者*/ 7class MovieLister 8{ 9    public Movie[] moviesDirectedBy(String arg) {10     

对于linux下system()函数的深度理解(整理)

对于linux下system()函数的深度理解(整理) (2013-02-07 08:58:54) 这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数中调用的命令也都一切正常.就没理这个bug,以为是其他的代码影响到这个,或是内核驱动文件系统什么的异常导致,昨天有出现了这个问题,就随手百了一下度,问题出现了,很多人都说system()函数要慎用要少用要能不用则不用,system()函数不稳定?

Java深度理解——Java字节代码的操纵

导读:Java作为业界应用最为广泛的语言之一,深得众多软件厂商和开发者的推崇,更是被包括Oracle在内的众多JCP成员积极地推动发展.但是对于 Java语言的深度理解和运用,毕竟是很少会有人涉及的话题.InfoQ中文站特地邀请IBM高级工程师成富为大家撰写这个<Java深度历险>专栏,旨在就Java的一些深度和高级特性分享他的经验.在一般的Java应用开发过程中,开发人员使用Java的方式比较简单.打开惯用的IDE,编写Java源代码,再利用IDE提供的功能直接运行 Java 程序就可以了.

深度解析javascript中的浅复制和深复制

原文:深度解析javascript中的浅复制和深复制 在谈javascript的浅复制和深复制之前,我们有必要在来讨论下js的数据类型.我们都知道有Number,Boolean,String,Null,Undefined,Object五种类型.而Object又包含Function,Array和Object自身.前面的五种类型叫做基本类型,而Object是引用类型.可能有人就要问,为什么要分基本类型和引用类型呢?后面你就会明白的. 我们首先来看看浅复制和深复制的简洁定义: 深复制:直接将数据复制给

深度理解java虚拟机读书笔记(二)HotSpot Java对象创建,内存布局以及访问方式

内存中对象的创建.对象的结构以及访问方式. 一.对象的创建 在语言层面上,对象的创建只不过是一个new关键字而已,那么在虚拟机中又是一个怎样的过程呢? (一)判断类是否加载.虚拟机遇到一条new指令的时候,首先会检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号代表的类是否被加载.解析并初始化.如果没有完成这个过程,则必须执行相应类的加载. (二)在堆上为对象分配空间.对象需要的空间大小在类加载完成后便能确定.之后便是在堆上为该对象分配固定大小的空间.分配的方式也有两种:

深度理解Key-Value Observing 键值观察

前言   在上一阶段的开发过程中,我们大量使用了 KVO 机制,来确保页面信息的及时同步.也因此碰到了很多问题,促使我们去进一步学习 KVO 的相关机制,再到寻找更好的解决方案.鉴于 KVO 让人欲仙欲死的使用经历,在这里做一个简单分享.此分享的目的,更多的是在于点出 KVO 相关的技术点,供我们大家在学习和使用过程中做一个参考. 对于 KVO 的背后机制感兴趣的同学,可以直接看第三部分,KVC 和 isa-swizzling . 对于 替代方案感兴趣的同学,请直接跳到末尾的第五部分,有列出了目

深度理解Android InstantRun原理以及源码分析

深度理解Android InstantRun原理以及源码分析 @Author 莫川 Instant Run官方介绍 简单介绍一下Instant Run,它是Android Studio2.0以后新增的一个运行机制,能够显著减少你第二次及以后的构建和部署时间.简单通俗的解释就是,当你在Android Studio中改了你的代码,Instant Run可以很快的让你看到你修改的效果.而在没有Instant Run之前,你的一个小小的修改,都肯能需要几十秒甚至更长的等待才能看到修改后的效果. 传统的代

深度理解IIS下部署ASP.NET Core2.1 Web应用拓扑图

原文:深度理解IIS下部署ASP.NET Core2.1 Web应用拓扑图 IIS部署ASP.NET Core2.1 应用拓扑图 我们看到相比Asp.Net, 出现了3个新的组件:ASP.NET Core Module.Kestrel.dotnet.exe, 后面我们会理清楚这三个组件的作用和组件之间的交互原理. 引入Kestrel的原因 进程内HTTP服务器,与老牌web服务器解耦,实现跨平台部署 IIS.Nginx.Apache等老牌web服务器有他们自己的启动进程和环境:为了实现跨平台部署