链表

链表

链表是由节点构成的,这个节点我们可以通过建立一个类来实现它。这个类我们通常选用内部类。

class TestLink{
	class Entry{
		int data;
		Entry next;
		public Entry() {
			next = null;
		}
		public Entry(int data) {
			this.data = data;
			next = null;
		}
	}
}

链表分为有头结点的链表和无头节点的链表,头结点不储存数据。本篇博客用的是头结点的链表。
注意链表要创建一个构造方法初始化头节点,否则会产生空指针异常

	Entry head;//成员变量
	public TestLink() {//构造函数
		head = new Entry();
	}

1.头插

	public void insertHead(int val) {
		Entry cur = new Entry(val);//插入的点
		cur.next = head.next;//把插入的点next指向head的下一个节点
		head.next=cur;//head的next指向插入的点
	}

2.尾插

遍历链表的时候要注意while(cur.next!=null)和while(cur!=null)的区别。
前者遍历完cur是链表尾元素,后者遍历完cur是null.

	public void insertTail(int val) {
		Entry goal = new Entry(val);//要插入的点
		Entry cur = head;//用来遍历链表
		while(cur.next!=null) {//当cur.next为null即cur已经在链表尾部,退出循环
			cur = cur.next;
		}
		cur.next=goal;//尾插

	}

3.获得链表长度

	public int getLength() {
		Entry cur = head;//用来遍历链表
		int count = 0;//计数器
		while(cur.next != null) {
			cur =cur.next;
			count++;
		}
		return count;
	}

4.任意位置插入

	public void insert(int val,int post) {
		Entry cur = head;//用来遍历链表
		if(post >= 0 && post <= this.getLength()) {//找到插入的位置前的的那一个节点
			for(int i=0;i<post;i++) {
				cur = cur.next;
			}
		}
		Entry entry = new Entry(val);
		 entry.next=cur.next;//插入
		 cur.next=entry;
	}

5.返回下标

public int valueOf(int val) {
		Entry cur = head.next;
		int count = 0;
		while(cur != null) {
			if(cur.val == val) {
				count++;
				return count;
			}
			count++;
			cur = cur.next;
		}
		return -1;
	}

6.删除指定元素

public void remove(int val) {
		int j = valueOf(val);
		if(j < 1) {
			return;	
		}
		Entry cur = head.next;
		Entry pr = head;
		for (int i = 1; i < j; i++) {
			cur = cur.next;
			pr =pr.next;
		}
		pr.next = cur.next;
		
	}

7.链表的逆置

	public Entry reverse(){
		Entry pre = null;//
		Entry newHead = null;//用来存放逆置后链表的头结点
		Entry cur = head;//用来遍历链表
		while(cur != null) {//当cur.next==null时即cur到尾部时再循环一次把cur变成头指针。
			Entry curNext = cur.next;
			if(curNext == null){
				newHead = cur;
			}
			cur.next = pre;
			pre = cur;
			cur = curNext;
		}
		return newHead;
	}

8.求倒数第k个元素

	public Entry getPost(int k) {
		if(head == null) {
			return -1;
		}
		Entry cur = head;//用来遍历链表
		if(k < 0 || k > this.getLength()) {//如果插入的位置小于零或大于链表长度返回null
			return null;
		}
		for(int i=0;i<this.getLength()-k+1;i++) {//找到倒数第k个位置
			cur =cur.next;
		}
		return cur;
		
	}

9.求两个链表是否相交

public boolean isCut(TestLink t1,TestLink t2) {
		TestLink.Entry head1 = t1.head;
		TestLink.Entry head2 = t2.head;
		int len1 = t1.getLength();
		int len2 = t2.getLength();
		int myLen = len1-len2;//两条链表的长度差
		if(myLen < 0) {//head1指向长链表表头
			head1 = t2.head;
			head2 = t1.head;
		}
		for(int i=0;i< myLen;i++) {//head1到在长链表上移动至和端链表对齐
			head1 = head1.next;
		}
		while(head1 != null && head2 !=null && head1 != head2) {//两个遍历节点同时向后移,如果到尾部结束循环或两个节点相交结束循环
			head1 = head1.next;
			head2 = head2.next;
		}
		if(head1 == head2) {//相交返回true
			return true;
		}
		return false;
	}

10.判断链表是否有环,并且求入口点和环长

public boolean judgeLoop() {
		Entry fast = head;//快节点
		Entry slow = head;//慢节点
		while(fast.next != null && fast.next.next != null) {//当快节点到尾部的时候循环结束,因为快节点每次要后移两格所以要加上fast.next.next不等于空的条件,否则会产生空指针异常
			fast = fast.next.next;
			slow = slow.next;
			if(fast == slow) {//相交返回true
				return true;
			}
		}
		return false;
	}

入口点

public int intoLoop(){
		 Entry fast = head;
		 Entry slow = head;
		 while(fast.next != null && fast.next.next != null){
			 fast = fast.next.next;
			 slow = slow.next;
			 if(fast == slow) {
				 break;
			 }
		 }
		 slow = head;
		 while(fast != slow){
			 fast = fast.next;
			 slow = slow.next;
		 }
		 return slow.data;
	 }

环长

当快慢节点第二次相遇时,慢节点从第一次到第二次相遇走的距离即环长。

public int getLoopLength() {
		Entry fast = head;
		Entry slow = head;
		boolean  tag = false;
		int length = 0;
		while(fast.next != null && fast.next.next != null) {
			fast = fast.next.next;
			slow = slow.next;
			if(fast == slow && tag == true) {
				break;
			}
			if(fast == slow && tag == false) {
				tag =true;
			}
			if(tag == true ) {
				length++;
			}
		}
		return length;
	}

11.合并两个链表

将两个递增链表合并成一个递增链表

public static Entry mergeLink(Link l1,Link l2) {

		Link.Entry p1 = l1.head.next;
		Link.Entry p2 = l2.head.next;
		Link.Entry newHead = null;
		if(p1.data<p2.data) {//确认头结点(值小的为头结点)
			newHead = l1.head;
		}else {
			newHead = l2.head;
		}
		Link.Entry tmpHead = newHead;//tmpHead相当于一个缝衣服的针将两个链表串起来
		while(p1 != null && p2 != null){
			if(p1.data < p2.data){
				tmpHead.next = p1;
				p1 = p1.next;
			}else{
				tmpHead.next = p2;
				p2 = p2.next;
			}
			tmpHead = tmpHead.next;
		}
		if(p1 != null){//如果p1链表没结束,就把p1后面的串上去
			tmpHead.next = p1;
		}
		if(p2 != null){//如果p2链表没结束,就把p2后面的串上去
			tmpHead.next = p2;
		}
		return newHead;
		
	}
	 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值