链表顺序表常见面试题(2)——Java语言实现

逆置/反转单链表
同从尾到头打印单链表一样,我们可以分别采用递归和栈来进行操作。
单链表排序(冒泡排序&快速排序)
冒泡排序:对相邻的两个节点的值进行比较,若是逆序则交换其值。
package com.struct.interview_question.list_interview_question.listsort;

public class BubbleSort {
    //已知头结点,对链表进行冒泡排序
    public ListNode bubbleSort(ListNode head) {
        //只有一个节点或者链表为空的情况
        if (head == null || head.nextNode == null) {
            return head;
        }
        //current用来保存当前节点,tail用来保存尾节点
        ListNode current = null;
        ListNode tail = null;
        current = head;
        while(current.nextNode!=tail){
            while(current.nextNode!=tail){
                //前者大于后者则交换两者的顺序
                if(current.data>current.nextNode.data){
                    int temp = current.data;
                    current.data = current.nextNode.data;
                    current.nextNode.data = temp;
                }
                current = current.nextNode;
            }
            //重置tail为当前节点,current为现在的head
            tail = current;
            current = head;
        }
        return head;
    }
}
  @Test
    public void test_BubbleSort(){
        ListNode listNode = new ListNode(8);
        listNode.nextNode = new ListNode(4);
        listNode.nextNode.nextNode = new ListNode(2);
        listNode.nextNode.nextNode.nextNode = new ListNode(5);
        BubbleSort bubbleSort = new BubbleSort();
        ListNode head = bubbleSort.bubbleSort(listNode);
        while (head!=null){
            System.out.print(head.data+"->");
            head = head.nextNode;
        }
    }
快速排序:以一个链表的头节点的值作为基准值,依次遍历节点,
         即可得到一个小于基准值的链表和一个大于基准值的链表,
         我们可以采用递归对大于和小于基准值的两个链表也采用快速排序。
package com.struct.interview_question.list_interview_question.listsort;

public class QuickSort {
    public ListNode quickSort(ListNode begin, ListNode end) {
        if (begin == null || begin == end) {
            return begin;
        }
        //找到基准点
        ListNode index = divide(begin, end);
        //对基准点前元素进行操作
        quickSort(begin, index);
        //对基准点后元素进行操作
        quickSort(index.nextNode, end);
        return begin;
    }

    public static ListNode divide(ListNode begin, ListNode end) {
        //没有元素或者只有一个元素
        if (begin == null || begin == end) {
            return begin;
        }
        // 以头结点为基准对元素进行划分
        int value = begin.data;
        ListNode index = begin;
        ListNode cur = begin.nextNode;
        while(cur!=null){
            if(cur.data<value){
                index = index.nextNode;
                //交换结点的值
                int temp = cur.data;
                cur.data = index.data;
                index.data = temp;
            }
            cur = cur.nextNode;
        }
        //交换基准值和index结点的值
        begin.data = index.data;
        index.data = value;
        //返回基准值
        return index;
    }
}
@Test
    public void test_QuickSort(){
        ListNode listNode = new ListNode(8);
        listNode.nextNode = new ListNode(4);
        listNode.nextNode.nextNode = new ListNode(2);
        listNode.nextNode.nextNode.nextNode = new ListNode(5);
        ListNode end = listNode.nextNode.nextNode.nextNode;
        QuickSort quickSort = new QuickSort();
        quickSort.quickSort(listNode,end);
        ListNode head = quickSort.quickSort(listNode,end);
        while (head!=null){
            System.out.print(head.data+"->");
            head = head.nextNode;
        }
    }
合并两个有序链表,合并后依然有序
对两个有序链表进行合并
step1:判断两个链表是否为空:如果链表1为空,则直接返回链表2;如果链表2为空,直接返回链表1;
step2:若两个链表都不为空,比较头结点head1和head2的大小,选出较小的作为合并后链表的头结点,
同时将小的head向后移以方便后续的比较
step3:设置一个临时变量,用来后续连接其他节点
step4:再比较head1和head2的大小,找出较小的,作为合并后链表的第二小节点,用temp.next来表示,同样再进行后移。
step5:重复上述操作,直至head1或者head2为null
step6:当head1或head2一个为空时,表明有一个链表已经全部放入新的链表中,直接将不为空的链表拼接在其后。
package com.struct.interview_question.list_interview_question.combinelist;

import com.struct.interview_question.list_interview_question.listsort.ListNode;

/**
*@Description: 合并两个有序链表合并后依然有序
*@Author: dyy
*/
public class CombineTwoList {
    public ListNode combineList(ListNode head1,ListNode head2){
        //链表1为空链表
        if(head1==null){
            return head2;
        }
        //链表2为空链表
        if(head2==null){
            return head1;
        }
        //两个链表均为空链表
        if (head1==null&&head2==null){
            return null;
        }
        //定义新的头结点
        ListNode head =null;
        //以升序排序为准
        //若链表1的头结点小于链表2的头结点,则以链表1的头结点为新的头节点
        if(head1.data<=head2.data){
            head = head1;
            //对节点进行后移操作,以便选出小的节点
            head1 = head1.nextNode;
        }else{
            //若链表1的头结点大于链表2的头结点,则以链表2的头结点为新的头节点
            head = head2;
            head2 = head2.nextNode;
        }
        //临时节点,用来保存下一个小节点的指向
        ListNode temp = head;
        //对头结点的后续节点进行大小的比较,找出第二小节点,直到有一个链表为空
        while (head1!=null&&head2!=null){
            if(head1.data<=head2.data){
               temp.nextNode = head1;
               head1 = head1.nextNode;
            }else{
                temp.nextNode = head2;
                head2 = head2.nextNode;
            }
            temp = temp.nextNode;
        }
        //当链表1为空时,直接拼接链表2
        if(head1 == null){
            temp.nextNode = head2;
        }
        //当链表2为空时,直接拼接链表1
        if(head2 == null){
            temp.nextNode = head1;
        }
        return head;
    }
}
 @Test
    public void test_CombineTwoList(){
        ListNode head1 = new ListNode(1);
        ListNode head2 = new ListNode(2);
        head1.nextNode = new ListNode(3);
        head1.nextNode.nextNode = new ListNode(5);
        head1.nextNode.nextNode.nextNode = new ListNode(7);
        head2.nextNode = new ListNode(4);
        head2.nextNode.nextNode = new ListNode(6);
        head2.nextNode.nextNode.nextNode = new ListNode(8);
        CombineTwoList combineTwoList = new CombineTwoList();
        ListNode newNode = combineTwoList.combineList(head1,head2);
        while (newNode!=null){
            System.out.print(newNode.data+"->");
            newNode = newNode.nextNode;
        }
    }

猜你喜欢

转载自blog.csdn.net/qq_40409115/article/details/81224388
今日推荐