链表及其基本操作的JAVA实现。

先来段代码:

package LinkList;

import java.util.Hashtable;

public class LinkList {

	Node head = null;

	public void addNote(int data) {

		Node newNode = new Node(data);

		if (head == null) {
			head = newNode;
			return;
		}
		Node intermediate = head;
		while (intermediate.next != null) {
			intermediate = intermediate.next;
		}
		intermediate.next = newNode;
	}

	public int length() {
		int length = 0;
		Node tmp = head;
		while (tmp != null) {
			length++;
			tmp = tmp.next;

		}
		return length;
	}

	/**
	 * @param index:delete
	 *            index node.
	 * 
	 * 
	 */
	public boolean deleteindexnode(int index) {
		if (index < 1 || index > length()) {
			return false;
		}
		if (index == 1) {
			head = head.next;
			return true;
		}
		int i = 1;
		Node prenode = head;
		Node currnode = prenode.next;
		while (currnode != null) {
			if (i == index) {
				prenode.next = currnode.next;
			}
			i++;
			prenode = currnode;
			currnode = currnode.next;
		}

		return true;
	}

	public Node ordlist() {

		int temp = 0;
		Node cur = head;
		Node ne = cur.next;
		if (cur == null || ne == null) {
			return head;
		}
		while (cur.next != null) {
			while (ne != null) {
				if (cur.data > ne.data) {

					temp = cur.data;
					cur.data = ne.data;
					ne.data = temp;
				}
				ne = ne.next;
			}
			cur = cur.next;
			ne = cur.next;
		}
		return head;
	}

	public void printList() {
		Node temp = head;
		while (temp != null) {

			System.out.println(temp.data);
			temp = temp.next;
		}
	}
	public Node searchMidNode(){
		
		Node p =this.head;
		Node q=this.head;
		while (p!=null&&p.next!=null&&p.next.next!=null) {
			p = p.next.next;
			q = q.next;
		}
		return q;
	}

	public void deleteDuplecate() {

		Hashtable<Integer, Integer> hashtable = new Hashtable<Integer, Integer>();
		Node pre = head;
		Node cur = pre.next;
		while (cur != null) {
			if (hashtable.containsKey(cur.data)) {
				pre.next = cur.next;
			} else {
				hashtable.put(cur.data, 1);
				pre = cur;
			}
			cur = cur.next;
		}

	}

	/*
	 * public void deleteDuplecatebyErgodic() {
	 * 
	 * Node cur = head; if (cur == null) { return; } // 外循环 while (cur != null)
	 * { Node ne = cur; // 内循环 while (ne.next!= null) { if (cur.data ==
	 * ne.next.data) { ne.next = ne.next.next; } ne = ne.next; } // 内循环结束 cur =
	 * cur.next; } // 外循环结束
	 * 
	 * }
	 */
	public void reverseList() {

		Node pReverseHead = head;
		Node pNode = head;
		Node pPrev = null;
		while (pNode != null) {
			Node pNext = pNode.next;
			if (pNext == null) {
				pReverseHead = pNode;
			}
			pNode.next = pPrev;
			pPrev = pNode;
			pNode = pNext;
		}
		this.head = pReverseHead;

	}

	public void printListReversely(Node head){

		if (head!=null) {
			printListReversely(head.next);
			System.out.println(head.data);
		}
		
		
	}
	public static void main(String[] args) {

		LinkList list = new LinkList();
		list.addNote(1);
		list.addNote(8);
		list.addNote(4);
		list.addNote(6);
		list.addNote(4);
		list.addNote(8);
		list.addNote(8);
		list.addNote(7);
		list.addNote(1);
		System.out.println("length:" + list.length());
		System.out.println("before:");
		list.printList();
		list.printListReversely(list.head);
		System.out.println("逆序输出");
		System.out.println("下面是中间结点:");
		System.out.println(list.searchMidNode().data);
//		list.printList();
//		list.ordlist();
//		System.out.println("Then");
//		list.printList();
		System.out.println("Reverse:");
		list.reverseList();
		list.printList();
		// System.out.println("Final");
		// list.deleteDuplecate();
		// list.printList();
	}
}

class Node {

	Node next;
	int data;

	public Node(int data) {
		this.data = data;
	}
}
上面这段代码包含了链表的一些基本操作。

  如何在不知道头指针的情况下删除指定结点?分两种情况来讨论:

  1.如果待删除的结点是尾结点,那么无法删除。

  2.如果待删除的结点不是尾部节点,那么可以通过交换该结点与其后继结点的值,然后删除后继结点。

下面是具体的代码实现:

	public Boolean deleteNode(Node node) {
		if (node.next == null) {
			return false;
		}
		int temp = node.data;
		node.data = node.next.data;
		node.next.data = temp;
		node.next = node.next.next;
		return true;
	}

如何判断2个链表结点相交?如果2个链表相交,则最后一个交点处肯定是尾结点(如果不是尾结点,那么肯定存在某个分叉的结点,而该结点会有2个指向,这显然是不可以的)。所以只要判断尾结点是否相同即可。下面是实现:

	public Boolean isIntersect(Node p,Node q){
		
		if (p==null||q==null) {
			return false;
		}
		Node ptail=p;
		while (ptail.next!=null) {
			ptail=ptail.next;
		}
		Node qtail = q;
		while (qtail.next!=null) {
			qtail=qtail.next;
		}
		
		return qtail==ptail;//不需要使用data,因为都是尾结点,所以qtail.next和ptail.next都是null,实际比较的还是data。
	}
继续讨论,如果2个链表相交,那么如何寻找他们相交的第一个结点呢,接下来分析一下:如果给定2个相交的链表,那么这2个链表肯定有长有短,假定长链表的长度为a,短链表的长度为b,则长链表从a-b处与短链表同时遍历比较即可。这样即可找到第一个,甚至可以找到任意的一个他们共有的结点。下面是具体实现:

	public Node searchFirstCommon(Node p, Node q) {

		// 首先判断是否相交,相交才能执行寻找第一个结点的操作。
		if (!this.isIntersect(p, q)) {
			return null;
		}
		int plenth = 0;
		int qlenth = 0;
		while (p != null) {// 找长度
			plenth++;
			p = p.next;
		}
		while (q != null) {// 找长度
			qlenth++;
			q = q.next;
		}
		// 将长链表“缩短”再遍历
		Node pNode = p;
		Node qNode = q;
		if (plenth > qlenth) {
			int t = plenth - qlenth;
			while (t != 0) {
				pNode = pNode.next;
				t--;
			}
		} else {
			int t = qlenth - plenth;
			while (t != 0) {
				qNode = qNode.next;
				t--;
			}
		}
		// 接下来同时遍历。
		while (pNode != qNode) {
			pNode = pNode.next;
			qNode = qNode.next;
		}
		return qNode;

	}


上述算法只需要分别遍历一次两个链表,时间复杂度为O(len1+len2),如果调用之前我们写过的统计长度和判断相交的方法,需要遍历2遍链表(每个方法遍历一遍,而我们这样写,在遍历一遍的同时做了两件事情:统计长度和得到尾结点,从而判断是否相交,不过这样做耦合性较差)。因此效率偏低。但是那样做会使得代码简洁,可用性强。

参考书:《JAVA程序员面试笔试宝典》   -----何昊、薛鹏、叶向阳 编著

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值