这篇博文 主要总结链表在应用时的几个重要案例。学习之前,最好能够掌握链表相关的一些基础知识,以及链表中数据的插入、删除操作如何实现等等,这些网上资料很多,这里没有做过多介绍,不熟悉的同学可以看代码之前简单了解一下。
1.单链表反转
链表中环的检测
求中间节点
删除链表中第n个结点
删除链表中倒数第n个节点
import java.util.Scanner;
/**
* @author xjh 2018.10.10
*
*/
class Node{ //节点类
int data;
Node next;
Node(int data){
this.data=data;
}
}
public class SingleLinkedeList {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in=new Scanner(System.in);
String t=in.nextLine(); //首先用String接收控制台输入的所有数字
char[] s=t.toCharArray(); //转换为char型
Node[] node=new Node[s.length];
for(int i=0;i<s.length;i++){
node[i]=new Node(s[i]-'0'); //得到int型 存入单链表节点中
}
for(int i=0;i<s.length;i++){
if(i==s.length-1){ //最后一个节点,指针指向空
node[i].next=null; //null为单链表 node[0]则为循环链表
}
else node[i].next=node[i+1];
}
printAll(node[0]); //首先输出原有的链表顺序 这里如果时循环链表的话 则不能执行这条语句 因为会进入死循环
// printAll(reverse(node[0])); //输出单链表反转后的链表顺序
System.out.println("It's CircleLinkedList ? "+CheckCircle(node[0]));
System.out.println("middleNode "+middleNode(node[0]).data);
int delete=3; //删除第n个节点
// printAll(deleteNode(node[0],delete));
printAll(deleteNodeToEnd(node[0],delete));
}
public static void printAll(Node head){
Node t=head;
while(t!=null){
System.out.print(t.data+" ");
t=t.next;
}
System.out.println();
}
/**
* 单链表反转
* @param p
* @return head
*/
public static Node reverse(Node p){
Node head=null;
Node previousNode=null; //先前节点指针
Node currentNode=p;
while(currentNode!=null){ //非空链表
Node nextNode=currentNode.next;
if(nextNode==null){ //以到达最后一个节点
head=currentNode;
}
currentNode.next=previousNode; //指向前面一个节点(头节点则指向null)
previousNode=currentNode;
currentNode=nextNode; //currentNode指向原来链表的下一个节点
}
return head;
}
/**
* 检测来链表是否有环(循环链表)
* @param p
* @return
*/
public static boolean CheckCircle(Node p){
if(p==null)
return false;
Node a=p;
Node b=p;
while(a!=null&&a.next!=null){
//这里利用快慢两个指针 主要为了让考虑如果链表长度特别大时,单一指针节点往后遍历时间复杂度高
a=a.next.next;
b=b.next;
if(a==b)
return true;
}
return false;
}
/**
* 求链表中间节点(注意这里的求解方法只用在单链表中,不适合在循环链表)
* @param p
* @return
*/
public static Node middleNode(Node p){
if(p==null)
return null;
Node a=p;
Node b=p;
while(a!=null&&a.next!=null){
//这里利用快慢两个指针 主要为了让考虑如果链表长度特别大时,单一指针节点往后遍历时间复杂度高
a=a.next.next;
b=b.next;
}
return b; //b就是链表中间节点
}
/**
* 删除链表中第n个结点
* @param p
* @return
*/
public static Node deleteNode(Node p,int delete){
Node n=p;
while(n!=null&&--delete>1){
n=n.next;
}
if(n==null) //链表中一共没有n个节点,无法实现删除操作
return p;
n.next=n.next.next; //删除指定的元素
return p;
}
/**
* 删除链表中倒数第n个节点
* 思路:首先利用一个指针p1找到第n个节点,然后另外一个指针p2从头节点出发 两个指针往后遍历,p1到达尾节点时 p2刚好为倒数第n个节点
* @param p
* @param delete
* @return
*/
public static Node deleteNodeToEnd(Node p,int delete){
Node p1=p;
int i=1;
while(p1!=null&&i<delete){
p1=p1.next;
++i;
}
if(p1==null) //链表一共没有n个节点,无法实现删除操作
return p;
Node p2=p;
Node pre=null;
while(p1.next!=null){
//往后遍历链表节点
p1=p1.next;
pre=p2;
p2=p2.next;
}//循环结束时 p1为尾节点,p2为倒数第n个节点 pre为倒数第n+1个节点
pre.next=pre.next.next;
return p;
}
}
2.两个有序链表的合并
import java.util.Scanner;
/**
* 两个有序单链表的合并
* @author xjh 2018.10.10
*
*/
public class SingleLinkedeList2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//首先构建两个升序单链表a b
int[] t1={1,3,5,7,9};
Node[] a=new Node[t1.length];
for(int i=0;i<t1.length;i++){
a[i]=new Node(t1[i]); //得到int型 存入单链表节点中
}
for(int i=0;i<t1.length;i++){
if(i==t1.length-1){ //最后一个节点,指针指向空
a[i].next=null; //null为单链表 node[0]则为循环链表
}
else a[i].next=a[i+1];
}
int[] t2={2,4,6,8,10};
Node[]b=new Node[t2.length];
for(int i=0;i<t2.length;i++){
b[i]=new Node(t2[i]); //得到int型 存入单链表节点中
}
for(int i=0;i<t2.length;i++){
if(i==t2.length-1){ //最后一个节点,指针指向空
b[i].next=null; //null为单链表 node[0]则为循环链表
}
else b[i].next=b[i+1];
}
printAll(MergeSort(a[0],b[0]));
}
public static void printAll(Node head){
Node t=head;
while(t!=null){
System.out.print(t.data+" ");
t=t.next;
}
System.out.println();
}
/**
* 合并两个有序链表
* @param a
* @param b
* @return
*/
public static Node MergeSort(Node a,Node b){
if(a==null) return b;
if(b==null) return a;
Node p=a;
Node q=b;
Node head;
//首先确定合并链表的头节点
if(p.data<q.data){
head=p;
p=p.next;
}else{
head=q;
q=q.next;
}
Node r=head;
//两个链表节点的元素依次进行比较,r指针有序连接
while(p!=null&&q!=null){
if(p.data<q.data){
r.next=p;
p=p.next;
}else{
r.next=q;
q=q.next;
}
r=r.next;
}
//当某个链表遍历提前结束时,r直接连接另一个为遍历完的有序链表
if(p!=null){
r.next=p;
}else{
r.next=q;
}
return head;
}
}