1. 程式人生 > >java實現連結串列(模擬LinkedList)

java實現連結串列(模擬LinkedList)

      眾所周知,連結串列是由一個個節點連線在一起,這裡我們就先建立一個節點類,為了達到模擬效果,我們選擇建一個Node的靜態內部類。

我們要想模擬LinkedList,就得先了解LinkedList的類包含的方法:

 add(Object)   dd(int,Object)   addFirst   addLast   get(int index)   remove    getIndex  removeFirst  removeLast等

以及LinkedList 所實現的介面


    我們為了要使用foreach語句遍歷,就必須實現Iterable介面。附上程式碼:

import java.util.Iterator;
public class MyLinkedList<T> implements Iterable<T>{
	private Node<T> first;//指向第一個節點的工作指標
	private Node<T> current;//指向最後一個節點的工作指標
	private int size=0;//統計連結串列長度
	private static class Node<T>{
		T data;
		Node<T> next;
	}
	//獲取長度
	public int size(){
		return size;
	}
	//新增節點
	public void add(T data){
		Node<T> newNode=new Node<T>();
		newNode.data=data;
		
		if(first==null){
			first=newNode;
			current=newNode;
			size++;
			return;
		}
		current.next=newNode;
		current=newNode;
		size++;
	}
	//插入第一個位置
	public void addFirst(T data){
		Node<T> newNode=new Node<T>();
		newNode.data=data;
		
		if(first==null){
			first=newNode;
			current=newNode;
			size++;
			return;
		}
		newNode.next=first;
		first=newNode;
		size++;
	}
	public void addLast(T data){
		add(data);
	}
	//根據索引新增節點
	public void add(int index,T data){
		Node<T> newNode=new Node<T>();
		newNode.data=data;		
		
		Node node=getNode(index);//指向指定索引之前的節點		
		
		if(node==null){
			addFirst(data);
			return;
		}
		newNode.next=node.next;
		node.next=newNode;
		size++;
	}
	/**
	 * 得到指定索引的資料
	 * @param index
	 * @return 資料
	 */
	public T get(int index){
		return getNode(index).next.data;
	}
	/**
	 * 得到指定索引的前一個節點
	 * @param index
	 * @return
	 */
	private Node<T> getNode(int index) {
		Node<T> node=null;
		if(index==0){
			//插入到第一個
			return null;
		}
		if(index<size){
			//插入中間
			node=first;
			for(int i=1;i<index;i++){
				node=node.next;
			}
			return node;
		}
		return current;
	}
	/**
	 * 迭代器
	 */
	public Iterator<T> iterator(){
		return new Iterator<T>() {
			Node<T> cur;
			@Override
			public boolean hasNext() {
				if(cur==null && first!=null){
					cur=first;
					return true;
				}
				if(cur.next!=null){
					cur=cur.next;
					return true;
				}
				return false;
			}
			@Override
			public T next() {
				return cur.data;
			}
		};
	}
	/**
	 * 移除資料
	 * @param data
	 */
	public void remove(T data){
		//查詢資料的索引
		int index=getIndex(data);
		remove(index);
	}
	/**
	 * 通過資料查詢第一次出現的索引
	 * @param data
	 * @return
	 */
	private int getIndex(T data) {
		Node node=first;
		for(int i=0;i<size;i++){
			if(node.data.equals(data)){
				return i;
			}
			node=node.next;
		}
		return -1;
	}
	/**
	 * 移除指定索引的資料
	 * @param index
	 */
	public void remove(int index){
		Node prev=getNode(index);
		Node node=getNode(index+1);
		prev.next=node.next;
		size--;
	}
	/**
	 * 移除第一個
	 */
	public void removeFirst(){
		first=first.next;
		size--;
	}
	/**
	 * 移除最後一個
	 */
	public void removeLast(){
		//查詢倒數第二個節點
		Node node=getNode(size-1);
		node.next=null;
		current=node;
		size--;
	}
	/**
	 * 修改指定索引的資料
	 * @param index
	 * @param newData
	 */
	public void set(int index,T newData){
		//得到指定索引節點
		Node node=getNode(index+1);
		if(node==null){
			node=first;
		}
		//修改節點上的資料
		node.data=newData;
	}
}


到這裡我們基本模擬了LinkedList類的所有方法,我們趕緊來測試下:

public class Demo {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		MyLinkedList<String> list=new MyLinkedList<String>();
		list.add("AAA");
		list.add("BBB");
		list.add("CCC");
		list.addFirst("DDD");
		list.addLast("EEE");
		list.add(2,"FFF");
		
		for(String s:list){
			System.out.println(s);
		}
		String s=list.get(2);
		System.out.println("下標為2的元素:"+s);
		
		list.set(2, "TEST");
		System.out.println("Size:"+list.size());
		list.removeFirst();
		list.removeLast();
		list.remove(2);
		System.out.println("------------------");
		for(String st:list){
			System.out.println(st);
		}
	}

}

這裡我們附上效果圖: