Java实现 双链表互换任意两个节点

本文介绍了一种在双向链表中通过节点ID交换两个指定节点位置的方法,并提供了详细的Java实现代码。该方法首先查找两个指定ID的节点,然后根据它们的位置关系进行适当的链接调整以完成节点交换。

1、确定两个节点的先后顺序
2、next、prev互相交换顺序以及将换向前方的节点与之前的节点对接。(1.prev.next = 2)
3、判断是否相邻

链表类:

public class SLink {
    public SNode head;

    public SLink() {
        this.head = new SNode();
    }
    public boolean interChangeById(int id1,int id2) {
        SNode s = head;
        SNode node1 = null,node2 = null;
        int node1Count,node2Count;
        node1Count = node2Count = 0;

        if(id1 == id2) {
            return true;
        }

        /**
         * 向下遍历
         */
        while (s.next != null) {
            s = s.next;
            node1Count ++ ;
            if(s.student.stuId == id1) {
                /**
                 * 记录节点1
                 */
                node1 = s;
                break;
            }

        }

        s = head;
        while (s.next != null) {
            s = s.next;
            node2Count ++ ;
            if(s.student.stuId == id2) {
                /**
                 * 记录节点2
                 */
                node2 = s;
                break;
            }
        }


        if(node1 != null && node2 != null) {
            SNode temp = new SNode();
            /**
             * node1在后
             */
            if(node1Count > node2Count) {
                temp.next = node1.next;
                temp.prev = node1.prev;
                /**
                 * 记录那个节点就先处理那个节点
                 * 1、交换next
                 * 2、交换prev
                 * 3、设置之前节点的next(对接)
                 */
                node1.next = node2.next;
                node1.prev = node2.prev;
                node2.prev.next = node1;

                if(node1.next.equals(node1)) {
                    /**
                     * 说明两个节点相邻
                     */
                    node1.next = node2;

                    node2.next = temp.next;
                    node2.prev = node1;
                }else {
                    /**
                     * 说明节点不相邻
                     */
                    node2.next = temp.next;
                    node2.prev = temp.prev;
                    temp.prev.next = node2;
                }
            }else {
                /**
                 * node1在前
                 */
                temp.next = node2.next;
                temp.prev = node2.prev;

                node2.next = node1.next;
                node2.prev = node1.prev;
                node1.prev.next = node2;
                if(node2.next.equals(node2)) {
                    node2.next = node1;

                    node1.next = temp.next;
                    node1.prev = node2;
                }else {
                    node1.next = temp.next;
                    node1.prev = temp.prev;
                    temp.prev.next = node1;
                }
            }
            return true;
        }
        return false;
    }
    public void displayStudent() {
        SNode s = head;
        while (s.next != null) {
            s = s.next;
            System.out.println(s.student);
        }
    }
}

节点类:

public class SNode {
    public Student student;
    public SNode next;
    public SNode prev;

    public SNode(Student student, SNode prev,SNode next) {
        this.student = student;
        this.next = next;
        this.prev = prev;
    }
    public SNode() {
        this.student = null;
        this.next = null;
        this.prev = null;
    }
}

Student类:

public class Student {
    public int stuId;
    public String name;
    public int age;
    public String className;

    public Student(int stuId, String name, int age, String className) {
        this.stuId = stuId;
        this.name = name;
        this.age = age;
        this.className = className;
    }

    public int getStuId() {
        return stuId;
    }

    public void setStuId(int stuId) {
        this.stuId = stuId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    @Override
    public String toString() {
        return "Student{" +
                "stuId=" + stuId +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", className='" + className + '\'' +
                '}';
    }
}
<think>嗯,用户想了解中间插入节点两个链表互换节点操作。这两个都是链表的基本操作,但可能对初学者来说有点挑战。我需要先理清楚每个操作的具体步骤,然后用简单易懂的方式解释。 首先,中间插入节点链表的结构通常是节点包含数据和指向下一个节点的指针。中间插入意味着不是在头部或尾部,而是在某个特定位置插入。比如,用户可能想知道如何找到插入的位置,然后调整指针。这里可能需要区分单链表和双向链表,但用户没有特别说明,所以默认单链表可能比较合适。需要考虑遍历链表找到正确的位置,然后重新链接前后的节点。关键点是要先找到前驱节点,然后修改它的next指向新节点,同时新节点的next指向原来的下一个节点。如果不小心顺序弄反了,可能会导致链表断裂,所以步骤的顺序很重要。 然后是互换两个链表节点。这可能有两种情况:交换两个链表中某个位置的节点,或者交换两个链表的全部节点。用户的问题描述不太明确,所以可能需要假设是交换两个链表中某个特定位置的节点。例如,链表A的第i个节点链表B的第j个节点交换。这时候需要考虑节点的前驱和后继,同时处理两个链表中的指针。需要特别注意边界条件,比如节点是头节点或者尾节点的情况,这时候可能需要更新链表的头指针。如果两个节点相邻的话,处理起来会更复杂,容易形成环路,需要避免。 接下来,我需要组织语言,分步骤解释这两个操作。对于中间插入,先说明需要定位到插入位置的前一个节点,然后调整指针。对于互换节点,需要先找到各自的节点和它们的前驱,然后交换next指针,同时处理可能的头节点变化。例子可能会有帮助,比如用具体的节点值来说明步骤,这样用户更容易理解。 需要注意的是,用户可能对指针操作不太熟悉,所以尽量用图示化的语言,比如“断开”、“连接”这样的词汇。同时,要强调操作顺序的重要性,避免出现断链的情况。比如,在插入时,必须先让新节点指向下一个节点,再让前驱节点指向新节点,否则后面的节点就找不到了。 另外,代码示例可能会有帮助,但用户要求用中文回答,可能不需要具体的编程语言代码,而是用伪代码或者自然语言描述步骤。不过用户的问题里没有明确是否需要代码,所以可能只需要文字解释。 在结构上,先分别介绍两个操作,每个操作分步骤说明,可能加上注意事项。确保每个步骤清晰,逻辑正确。比如中间插入的步骤:遍历找到位置,调整指针;交换节点的步骤:找到节点和前驱,处理两个链表的指针变化。 最后,检查是否有遗漏的情况,比如链表为空,插入位置超出范围等,是否需要处理这些异常情况。不过用户可能只需要基本操作步骤,所以可以简要提到需要考虑这些情况,但重点放在正常流程上。</think>### 一、中间插入节点操作 #### 概念说明 在链表的非头尾位置插入新节点,需要定位插入点并调整相邻节点的指针关系。 #### 操作步骤 1. **定位前驱节点** 遍历链表找到插入位置的前一个节点(记为`prev`)。 2. **创建新节点** 初始化新节点`new_node`,存储目标数据。 3. **调整指针** ```text new_node.next = prev.next // 新节点指向原后继节点 prev.next = new_node // 前驱节点指向新节点 ``` #### 示例 原始链表:A → B → D → E 在B和D之间插入C: 1. 定位到前驱节点B 2. 新节点C.next = B.next (即D) 3. B.next = C 结果:A → B → C → D → E --- ### 二、两个链表互换节点操作 #### 概念说明 交换两个链表中的特定节点,需处理四个指针关系(两个链表各自的前驱节点指针+目标节点的指针)。 #### 操作步骤 1. **定位目标节点** 分别找到链表1中的节点`node1`及其前驱`prev1`,链表2中的节点`node2`及其前驱`prev2`。 2. **断开原连接** ```text prev1.next = node1.next // 链表1中移除node1 prev2.next = node2.next // 链表2中移除node2 ``` 3. **建立新连接** ```text // 将node1插入链表2 node1.next = prev2.next // node1接管原node2的后继 prev2.next = node1 // 链表2前驱指向node1 // 将node2插入链表1 node2.next = prev1.next // node2接管原node1的后继 prev1.next = node2 // 链表1前驱指向node2 ``` #### 示例 链表1:1 → 3 → 5 链表2:2 → 4 → 6 交换节点3和4: 1. 链表1中prev1=1, node1=3;链表2中prev2=2, node2=4 2. 断开:1→5,2→6 3. 连接:1→4→5,2→3→6 --- ### 关键注意事项 1. **边界处理** - 若节点是头节点,需特殊处理链表头指针 - 若节点是相邻节点,需避免循环引用 2. **时间复杂度** - 中间插入:O(n)(需遍历定位) - 节点交换:O(n + m)(两个链表分别遍历) 3. **内存安全** 操作指针时需确保不丢失节点引用,防止内存泄漏(如C/C++场景) 通过上述步骤,可以清晰地理解链表操作的核心逻辑:通过指针的断开和重连实现动态结构调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值