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