转载注明!! https://blog.csdn.net/qq_31842777/article/details/90610469
涉及:
链表创建、计算链表长度、遍历打印链表、插入、删除结点、链表反转、合并两个有序链表结果仍为有序链表、从尾到头打印链表。
直接上代码(含测试):
import java.util.Stack;
/*
*链表基本操作
*面试算法题
*/
public class MyLinkedList {
//定义头结点
public Node head;
//定义结点类
public static class Node{//类必须是static,后面测试会用到此类创建实例
int data;
Node next;
Node(){}
Node(int data){
this.data=data;
}
}
/*
*以下是表的基本操作
*/
//添加结点,以创建链表 遍历链表到尾结点,然后添加结点
public void addNode(Node node) {
Node temp=head;
//以下操作找到链表的尾结点,然后插入
while(temp.next!=null) {
temp=temp.next;
}
//如果temp.next为空,即到尾结点,加入新结点
temp.next=node;
}
//获取链表长度 从头遍历链表
public int getLength(Node head) {
if(head==null) {
return 0;
}
Node temp=head;
int length=1;
while(temp.next!=null) {
length++;
temp=temp.next;
}
return length;
}
/*
* 以下是算法题
*/
//1.从node遍历并打印链表
/*
* 如果head为空,返回空
* 如果head不为空,遍历并打印
*/
public static void print(Node node) {
if(node==null) {
return;
}
Node temp=node;
while(temp!=null) {
System.out.print("-->"+temp.data);
temp=temp.next;
}
System.out.println();
}
//2.插入操作:在指定位置插入结点
/*
* 链表下标从1开始
* index允许的范围是(1,getLength(head)+1]
* 如:长度为7的链表
*/
public void insertByIndex(int index,Node node) {
if(index<1||index>getLength(head)+1) {
return;
}
Node temp=head;
int length=1;
while(temp.next!=null) {
if((index-1)==length++) {//如插入到第4位,需在第三位开始操作,交换next值
node.next=temp.next;
temp.next=node;
}
temp=temp.next;
}
}
//3.删除操作
public void deleteByIndex(int index) {
if(index<1||index>getLength(head)) {
return;
}
Node temp=head;
int length=1;
while(temp.next!=null) {
if((index-1)==length++) {
temp.next=temp.next.next;
}
temp=temp.next;
}
}
//!!!插入删除不能插入删除第一个和最后一个结点,待优化!!!
//4.链表反转
/**
* 链表翻转操作的顺序对于迭代来说是从链头往链尾,而对于递归是从链尾往链头
* 递归方式:递归,在反转当前节点之前先反转后续节点
* 非递归方式:遍历,将当前结点的下一个结点缓存后更改当前结点指针
*/
//非递归实现
public static Node reverseList(Node head) {
if (head == null || head.next == null) {
return head;
}
Node current=head;
Node newHead=null;//反转后新链表的表头
Node next=null;//定义当前节点的下一个结点
while(current!=null) {
next=current.next;//保存当前结点的下一个结点,下次循环要用,因为后续操作会破坏current.next
current.next=newHead;//current当前结点指向newHead
//操作结束,current结点后移
newHead=current;
current=next;
}
return newHead;
}
//递归实现
public static Node reverseListRec(Node head) {
if(head==null||head.next==null) {
return head;
}
Node newHead=reverseListRec(head.next);//找到最后一个结点,并赋值给newHead
head.next.next=head;//新链表指向当前结点
head.next=null;//置空当前结点的下一个结点,避免形成环
return newHead;
}
/**
* 5.合并两个有序链表,合并之后链表依然有序
* 若合并前列表非有序,可先进行冒泡排序,再合并
* 思路:两种方式:1.创建一个新的链表,不断的将原来两个链表的数据接入新的链表,不破坏原链表
* 2.在原来两个链表上进行操作,将其中一个链表的数据不断的和另一个链表的数据进行比较,
* 如果第一个链表的数据比第二个大的话那就将第二个链表的数据放在第一个链表当前数据的前边,破环原链表
* 此处采用第一种
*/
public static Node mergeTwoLinkedList(Node head1,Node head2) {
//两链表为空,返回空
if(head1==null&&head2==null) {
return null;
}
//任意一个为空,返回另一个
if(head1==null) {
return head2;
}
if(head2==null) {
return head1;
}
//建立新链表
Node newHead;
Node temp;//建立temp结点,用于操作
//初始化新链表的头结点
if(head1.data<head2.data) {
newHead=head1;
temp=head1;//!!!!!
head1=head1.next;
}else {
newHead=head2;
temp=head2;
head2=head2.next;
}
//遍历两链表,将结果依次插入temp之后
while(head1!=null&&head2!=null) {
if(head1.data<head2.data) {
//初始化已经循环一次,追加
temp.next=head1;
head1=head1.next;
temp=temp.next;
}else {
temp.next=head2;
head2=head2.next;
temp=temp.next;
}
}
//若两个链表的任意一个没有比较完,追加到temp
if(head1!=null) {
temp.next=head1;
}
if(head2!=null) {
temp.next=head2;
}
return newHead;
}
/**
* 6.从尾到头打印单链表
* 思路:对于这种颠倒顺序的问题,实现要想到栈,后进先出!!!
* 故要么自己使用栈,要么系统使用栈(递归)
* 两种方式:1.自己使用栈
* 2.系统使用栈(递归)
*/
public static void printFromLast(Node head) {
if(head==null) {
return;
}
Stack<Node> stack=new Stack<>();
Node temp=head;
//入栈
while(temp!=null) {
stack.push(temp);
temp=temp.next;
}
//出栈
while(!stack.isEmpty()) {
System.out.println(stack.pop().data);
}
}
public static void printFromLastRec(Node head) {
if(head==null) {
return;
}
printFromLastRec(head.next);
System.out.println(head.data);
}
public static void main(String[] args) {
//创建链表实例
MyLinkedList LinkedList=new MyLinkedList();
LinkedList.head=new Node(0);
Node node1=new Node(1);
Node node2=new Node(2);
Node node3=new Node(4);
Node node4=new Node(6);
Node node5=new Node(7);
LinkedList.addNode(node1);
LinkedList.addNode(node2);
LinkedList.addNode(node3);
LinkedList.addNode(node4);
LinkedList.addNode(node5);
System.out.println("链表长度:"+LinkedList.getLength(LinkedList.head));
System.out.println("遍历并打印链表:");
MyLinkedList.print(LinkedList.head);
Node node6=new Node(9);
System.out.println("插入:");
LinkedList.insertByIndex(5,node6);
MyLinkedList.print(LinkedList.head);
System.out.println("删除:");
LinkedList.deleteByIndex(6);
MyLinkedList.print(LinkedList.head);
System.out.println("链表反转:");
System.out.println("非递归实现:");
LinkedList.head=MyLinkedList.reverseList(LinkedList.head);
MyLinkedList.print(LinkedList.head);
System.out.println("递归实现:");
LinkedList.head=MyLinkedList.reverseListRec(LinkedList.head);
MyLinkedList.print(LinkedList.head);
System.out.println("合并有序链表结果为有序链表:");
System.out.println("待合并的链表:");
MyLinkedList LinkedList1=new MyLinkedList();
LinkedList1.head=new Node(1);
Node node11=new Node(2);Node node12=new Node(3);Node node13=new Node(4);
LinkedList1.addNode(node11);LinkedList1.addNode(node12);LinkedList1.addNode(node13);
MyLinkedList.print(LinkedList1.head);
MyLinkedList LinkedList2=new MyLinkedList();
LinkedList2.head=new Node(2);
Node node9=new Node(3);Node node7=new Node(4); Node node8=new Node(5);
LinkedList2.addNode(node9);LinkedList2.addNode(node7);LinkedList2.addNode(node8);
MyLinkedList.print(LinkedList2.head);
System.out.println("结果:");
MyLinkedList newLinkedList=new MyLinkedList();
newLinkedList.head=MyLinkedList.mergeTwoLinkedList(LinkedList1.head,LinkedList2.head);
MyLinkedList.print(newLinkedList.head);
}
}
运行结果: