合并两个有序单链表(java实现)

合并两个有序单链表

思想:循环遍历两个链表,将小的值依次插入(此处用尾插哦)新的链表中。

为了防止思想短路,贴个图便于分析:合并两个有序单链表(java实现)_第1张图片

1. 普通循环实现

思路:对比数组来看,如果此题要求是将两个有序数组合并,那你第一步肯定是新建一个大小为两个数组大小之和的空数组,然后循环往新数组中添加数据。
添加的过程就是插入的过程,所以我们需要对链表定义一个尾插法的函数。

private static class Node {
     
        String data;
        Node next;

        public Node(String data) {
     
            this.data = data;
        }

		//尾插
        void addLast(Node node) {
     
            Node old = this;
            while (old.next != null) {
     
                old = old.next;
            }
            old.next = node;
        }
    }

接下来的事情就简单了

  • 定义新的链表
  • 循环比较两个列表,小的值用尾插法插入到新定义的链表中
  • 然后就是一些善后工作
public static Node mergeSortedNode(Node node1, Node node2) {
     
        Node renode = new Node("");//定义新的链表
        while (node1 != null) {
     
            Node old = node2;//此处需要赋值给新的链表来循环
            while (old != null) {
     
                if (Integer.parseInt(node1.data) >= Integer.parseInt(old.data)) {
     
                    Node node = new Node(old.data);
                    renode.addLast(node);
                    node2 = node2.next;//node2后移一位
                }
                old = old.next;
            }
            Node node = new Node(node1.data);
            renode.addLast(node);
            node1 = node1.next;
        }
        if (node2 != null) {
     
            renode.addLast(node2);
        }
        return renode.next;//注意这里,由于新定义的链表第一个节点没有用(并非传参进来的链表内容,二十自己凭空创造的),故而最终将这个节点排除!
    }

以上是以新增方法addLast()的思想来实现。
如果不新增方法直接该如果操作呢?

public static Node mergeSortedNode1(Node node1, Node node2) {
     
        Node result = null;
        Node k = null;
        while (node1 != null) {
     
            Node item = node2;
            while (item != null) {
     
                if (Integer.parseInt(item.data) <= Integer.parseInt(node1.data)) {
     
                    if (result == null) {
     
                        result = item;
                        k = result;
                    } else {
     
                        result.next = item;
                        result = result.next;
                    }
                    node2 = node2.next;
                }
                item = item.next;
            }
            if (result == null) {
     
                result = node1;
                k = result;
            } else {
     
                result.next = node1;
                result = result.next;
            }
            node1 = node1.next;
        }
        if (node2 != null) {
     
            result.next = node2;
        }
        return k;
    }

本来打算定义result直接返回,最后发现每次都得移动result;即result=result.next 最终结果肯定是最后一个节点,所以定义一个节点k来保存新的结构。
以上实现均是以其中一个节点为依据,将此节点循环至尾节点,循环结束后如果另一个链表没有移动至尾节点,将剩余内容直接追加至后面。接下来将两个链表同时遍历:

public static Node mergeSortedNode2(Node node1, Node node2) {
     
        Node head = null;
        Node last = null;
        while (node1 != null && node2 != null) {
     
            if (Integer.parseInt(node1.data) <= Integer.parseInt(node2.data)) {
     
                if (head == null) {
     
                    head = node1;
                } else {
     
                    last.next = node1;
                }
                last = node1;
                node1 = node1.next;
            } else {
     
                if (head == null) {
     
                    head = node2;
                } else {
     
                    last.next = node2;
                }
                last = node2;
                node2 = node2.next;
            }
        }
        if (node1 != null) {
     
            last.next = node1;
        } else {
     
            last.next = node2;
        }
        return head;
    }

此种方法就需要判断到底哪个链表没有移动至尾节点

if (node1 != null) {
     
    last.next = node1;
} else {
     
    last.next = node2;
}

2.迭代实现

最后再来看最后一种简洁实现,迭代实现:

public static Node mergeSortedNode3(Node node1, Node node2) {
     
        if (node1 == null) {
     
            return node2;
        }
        if (node2 == null) {
     
            return node1;
        }
        Node head = null;
        if (Integer.parseInt(node1.data) <= Integer.parseInt(node2.data)) {
     
            head = node1;
            head.next = mergeSortedNode3(head.next, node2);
        } else {
     
            head = node2;
            head.next = mergeSortedNode3(node1, head.next);
        }
        return head;
    }

迭代的思想在于

假设 分步 细化

  • 假设mergeSortedNode3的作用就是将给定的两个链表合并你想要的样子,然后你需要就是给方法传参。
  • 首次进来后根据大小判断好之后,将head赋予初值:
 head = node1
  • 然后下一个值就是通过假设的已经成立的方法将下一个值填充好:
head.next = mergeSortedNode3(head.next, node2)
  • 最后添加终止条件!

没看错,结束了,然后再带个值验证一下!

其实迭代的思想就是分步,写出细分后的具体一步的实现内容,然后迭代。最后添加终止条件。
本例中的迭代终止条件就是链表为空,正如开头判断那样。

你可能感兴趣的:(链表,java,数据结构,算法)