经典案例-链表操作的几大经典例子 leetcode 单链表反转 环的检测 求中间节点 有序链表合并等

这篇博文 主要总结链表在应用时的几个重要案例。学习之前,最好能够掌握链表相关的一些基础知识,以及链表中数据的插入、删除操作如何实现等等,这些网上资料很多,这里没有做过多介绍,不熟悉的同学可以看代码之前简单了解一下。

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;
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值