单链表

407 阅读3分钟

单链表定义

/**
 * 单链表的定义
 */
public class ListNode {
    // 存表的元素
    public int value;
    // 指针
    public ListNode next;

    public ListNode(int value) {
        this.value = value;
    }
}
public class ListNodeTest {
    /**
     * 单链表反转链表
     * 时间复杂度o(n), 空间复杂度o(1)
     */
    public static ListNode reverseList(ListNode head) {
        // 当前结点的上一个结点
        ListNode pre = null;
        // 当前结点的下一个结点
        ListNode next = null;
        // 遍历
        while (head != null) {
            // 记录下一个结点的位置
            next = head.next;
            // 当前结点的尾指针(下一个结点)由原来的位置指向它前面的位置,也就是反转
            head.next = pre;
            // 前一个结点pre和当前结点的指针,都向后移一位
            pre = head;
            head = next;
        }
        // 返回反转之后的第一个结点(因为正常顺序的尾结点是null,所有反转时当前结点的值就是null)
        return pre; 
    }

    /**
     * 单链表取中间结点
     * 如果单链表个数是奇数,就取中间的结点
     * 如果单链表个数是偶数,就取中间两个中前面的那个
     * 思路: 规定了两个指针,一个快指针,一个慢指针,快指针每次走两步,慢指针每次走一步,
     *      当快指针走完之后,慢指针的位置就是中间结点的位置
     */
    public static ListNode getMid(ListNode head){
        if (head == null) {
            return head;
        }
        // 快指针,刚开始都是指向头部
        ListNode fast = head;
        // 慢指针,刚开始都是指向头部
        ListNode slow = head;
        // 因为快指针fast每次走两步,所有判断它的下一步和下两步为null时, 不能遍历
        while (fast.next != null && fast.next.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        // 返回慢指针的位置
        return slow;
    }

    public static void main(String[] args) {
        ListNode node1 = new ListNode(1);
        ListNode node2 = new ListNode(2);
        ListNode node3 = new ListNode(3);
        node1.next = node2;
        node2.next = node3;
        node3.next = null;
        System.out.println(getMid(node1).value);
        ListNode node = reverseList(node1);
        while (node != null) {
            System.out.print(node.value + " ");
            node = node.next;
        }
    }
}
/**
 * 合并两个有序链表
 */
public class ListNodeTest2 {
    /**
     * 采用递归实现, 两个有序链表
     * @param head1
     * @param head2
     * @return
     */
    public static ListNode mergeTwoList(ListNode head1, ListNode head2) {
        // 递归结束的条件
        if (head1 == null && head2 == null) {
            return null;
        }
        if (head1 == null) {
            return head2;
        }
        if (head2 == null) {
            return head1;
        }
        // 主要的逻辑
        // 声明合并之后的头结点
        ListNode head = null;
        if (head1.value > head2.value) {
            // 把head的头指针指向较小的那个
            head = head2;
            // head2.next:在剩余的结点中去找下一个结点
            head.next = mergeTwoList(head1, head2.next);
        } else {
            head = head1;
            head.next = mergeTwoList(head1.next, head2);
        }
        return head;
    }

    /**
     * 采用非递归的方式
     */
    public static ListNode mergeTwoList2(ListNode head1, ListNode head2) {
        // 思路:分别遍历两个链表,把另一个链表合并到当前链表中,把首节点大的每一个元素合并到首节点小的那个链表
        if (head1 == null || head2 == null) {
            return head1 != null ? head1 : head2;
        }
        // 两个链表的头结点比较,先找到头结点比较小的那个,作为基准链表
        ListNode head = head1.value < head2.value ? head1 : head2;
        // cur1 指向的链表是基准的链表
        ListNode cur1 = head == head1 ? head1 : head2;
        // cur2 指向另一个链表
        ListNode cur2 = head == head1 ? head2 : head1;
        ListNode pre = null; // cur1前一个元素
        ListNode next = null; // cur2 后一个元素
        while (cur1 != null && cur2 != null) {
            if (cur1.value <= cur2.value) {
                pre = cur1;
                cur1 = cur1.next;
            } else {
                next = cur2.next;
                pre.next = cur2;
                cur2.next = cur1;
                pre = cur2;
                cur2 = next;
            }
        }
        pre.next = cur1 == null ? cur2 : cur1;
        return head;
    }

    public static void main(String[] args) {
        ListNode node1 = new ListNode(1);
        ListNode node2 = new ListNode(2);
        ListNode node3 = new ListNode(3);
        ListNode node4 = new ListNode(4);
        node1.next = node3;
        node2.next = node4;
        ListNode node = mergeTwoList2(node1, node2);
        while (node != null) {
            System.out.print(node.value + " ");
            node = node.next;
        }
    }

}

参考资料:来源于网络