博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

单向链表学习笔记

Posted on 2011-09-25 16:38  袁立  阅读(193)  评论(0编辑  收藏  举报

1.链表接口定义

package com.ncs.datastructure.linklist;

public interface ILinkList {

	/**
	 * 链表是否为空
	 * @return
	 */
	public abstract boolean isEmpty();

	/**
	 * 在链表的第一个节点前插入节点
	 * @param data
	 */
	public abstract void addToHead(Object data);

	/**
	 * 在链表的最后一个节点追加节点
	 * @param data
	 */
	public abstract void addToTail(Object data);

	/**
	 * 删除链表中的第一个节点
	 * @return
	 */
	public abstract Object deleteFromHead();

	/**
	 * 删除链表中的最后一个节点
	 * @return
	 */
	public abstract Object deleteFromTail();

	/**
	 * 链表中是否存在指定的节点
	 * @param data
	 * @return
	 */
	public abstract boolean isContains(Object data);

	/**
	 * 删除指定的节点
	 * @param data
	 */
	public abstract void deleteNode(Object data);

}


2.单向链表的简单实现

package com.ncs.datastructure.linklist;

import java.io.Serializable;

/**
 * 单向链表
 * @author yuanli
 *
 */
public class SingleLinkList {
	
	/**
	 * 之所以定义为内部类,是因为用户并不关心链表节点的结构,而只关心链表存储的数据
	 * @author yuanli
	 *
	 */
	public class Node implements Serializable {

		private static final long serialVersionUID = -1413226342863254391L;

		public Object data;//数据域(用户关心的内容)
		public Node next;//引用域(指向下一个节点)(用户不关心的内容)
		
		public Node(Object data) {
			this(data,null);
		}
		
		public Node(Object data, Node next) {
			super();
			this.data = data;
			this.next = next;
		}
	}
	
	//表示链表的第一个节点
	protected Node head;
	
	//表示链表的最后一个节点
	protected Node tail;
	
	/**
	 * 链表是否为空
	 * @return
	 */
	public boolean isEmpty() {
		return (head == null || tail == null);
	}
	
	/**
	 * 在链表的第一个节点前插入节点
	 * @param data
	 */
	public void addToHead(Object data) {
		this.head = new Node(data,this.head);
		if (this.tail == null) this.tail = this.head;
	}
	
	/**
	 * 在链表的最后一个节点追加节点
	 * @param data
	 */
	public void addToTail(Object data) {
		if (!this.isEmpty()) {
			this.tail.next = new Node(data);
			this.tail = this.tail.next;
		} else {
			this.head = this.tail = new Node(data);
		}
	}
	
	/**
	 * 删除链表中的第一个节点
	 * @return
	 */
	public Object deleteFromHead() {
		Node current_head_node = this.head;
		if (this.head == this.tail) {
			this.head = this.tail = null;
		} else {
			this.head = this.head.next;
		}
		return current_head_node.data;
	}
	
	/**
	 * 删除链表中的最后一个节点
	 * @return
	 */
	public Object deleteFromTail() {
		Node current_tail_node = this.tail;
		if (this.tail == this.head) {
			this.head = this.tail = null;
		} else {
			//若想删除最后一个节点,则必须先找到倒数第二个节点,并将其next设为null
			//如何确定倒数第二个节点呢?如果那个节点的next指向的是tail,则说明是
			Node temp = this.head;
			for (; temp.next != this.tail; temp = temp.next);
			this.tail = temp;
			this.tail.next = null;
		}
		return current_tail_node.data;
	}
	
	/**
	 * 链表中是否存在指定的节点
	 * @param data
	 * @return
	 */
	public boolean isContains(Object data) {
		Node temp = this.head;
		for (; temp != null; temp = temp.next) {
			if (temp.data.equals(data)) return true;
		}
		return false;
	}
	
	/**
	 * 删除指定的节点
	 * @param data
	 */
	public void deleteNode(Object data) {
		if (!isEmpty()) {
			//如果只有一个节点
			if (this.head == this.tail && this.head.data .equals(data)) {
				this.head = this.tail = null;
				return;
			}
			//如果删除的是第一个节点
			if (this.head.data.equals(data)) {
				this.deleteFromHead();
				return;
			}
			//如果删除的是最后一个节点
			if (this.tail.data.equals(data)) {
				this.deleteFromTail();
				return;
			}

			//否则
			Node temp = this.head;
			for (; temp != null; temp = temp.next) {
				if (temp.next.data.equals(data)) {
					temp.next = temp.next.next;
					break;
				}
			}
		}
	}
	
	/**
	 * 遍历链表的所有节点,并打印出节点数据信息
	 */
	public void printAll() {
		Node temp = this.head;
		for (; temp != null; temp = temp.next) {
			System.out.println("node data is " + temp.data);
		}
	}
	
	public Node getHead() {
		return head;
	}

	public void setHead(Node head) {
		this.head = head;
	}

	public Node getTail() {
		return tail;
	}

	public void setTail(Node tail) {
		this.tail = tail;
	}

	
	/**
	 * @param args
	 */
	public static void main(String[] args) {

		//实例化一个单向链表对象
		SingleLinkList sll = new SingleLinkList();
		
		//向单向链表中添加节点
		sll.addToHead("node1");
		sll.addToTail("node2");
		sll.addToTail("node3");
		sll.addToTail("node4");
		//输出所有节点数据
		sll.printAll();
		
		//删除第一个节点
		sll.deleteFromHead();
		
		//删除最后一个节点
		sll.deleteFromTail();
		
		//输出所有节点数据
		sll.printAll();

		//链表中是否包含指定的节点
		boolean isExsist = sll.isContains("node11");
		System.out.println(isExsist);
		
		//删除指定的节点
		sll.deleteNode("node3");
		sll.printAll();
		
	}

}


总结:

1.单向链表的优点:插入节点效率高

2.单向链表的缺点:查询、删除节点效率低