算法與數據結構【Java】:普通單向鏈表

普通單向鏈表應該包含的數據和方法:

結點類(Node):


    屬性:
        AnyType value;    //任意類型的數據
        Node* next;        //指向下一個節點的指針
    方法:
        構造方法 Node(AnyType* value, Node* next);

鏈表類(LinkedList):


    Node* head;        //鏈表頭結點的指針
    Node* tail;        //鏈表尾結點的指針,可選
    int length;        //鏈表長度,可選

    int isEmpty();    //鏈表是否爲空
    int contains();    //鏈表是否包含某個值
    void addToHead(AnyType value);    //向鏈表頭添加數據
    void addToTail(AnyType value);    //向鏈表尾添加數據
    void addNode(AnyType value, int index)    //向鏈表指定下標處添加數據
    int deleteFromHead();    //從鏈表頭刪除一個數據,返回被刪除的數據
    int deleteFromTail();    //從鏈表尾刪除一個數據,返回被刪除的數據
    int deleteNode();    //刪除指定下標處的數據,返回被刪除的數據

 

實現每種方法的思路:


    1、因爲LinkedList類的屬性有:head,tail,length
        所以要根據不同情況更新三個屬性
    2、所以每種方法,都要處理:
        1)head發生變化
        2)tail發生變化
        的情況

下方是Java代碼:


//鏈表類
public class LinkedList {
	//
	Node head;	//鏈表頭結點的指針
	Node tail;	//鏈表尾結點的指針,可選
	int length;	//鏈表長度,可選
	
	int isEmpty() {			//鏈表是否爲空
		//頭結點爲空,鏈表爲空
		return head == null ? 1 : 0;	
	};	
	
	int contains(int value) {		//鏈表是否包含某個值
		//遍歷鏈表,查找值
		for (Node now=head; now!=null; now=now.next)
			if (now.value == value)
				return 1;
		return 0;
	}
	
	void addToHead(int value) {		//向鏈表頭添加數據
		//如果鏈表爲空,更新head和tail
		if (head == null) 
			head = tail = new Node(value);
		//否則直接添加
		else 
			this.head = new Node(value, this.head);
		this.length++;
	}
	
	void addToTail(int value) {		//向鏈表尾添加數據
		//如果鏈表爲空,更新head和tail
		if (head == null)
			head = tail = new Node(value);
		//否則直接添加
		else 
			tail = tail.next = new Node(value);
		length++;
	}
	
	void addNode(int value, int index) {	//向鏈表指定下標處添加數據
		//如果要添加的下標不合法,直接返回
		if (index <= 0) return;
		//如果鏈表爲空,且在第一個位置插入
		if (head == null && index == 1) {
			head = tail = new Node(value);
			length++;
			return ;
		}
		//如果鏈表爲空,要在非法位置插入
		else if (head == null && index != 1) {
			return ;
		}
		//如果在頭部插入,更新head
		if (index == 1) {
			head = new Node(value, head);
			length++;
			return ;
		}
		//在其他部位插入
		Node aheadOfAdd = null;
		int cnt = 1;
		//循環查找鏈表,找到index-1位置的結點,存入aheadOfAdd
		//使得循環停止的條件有兩個:
			//情況1:aheadOfAdd=null單獨成立,說明要添加的序號已經超出現有的鏈表長度
			//情況2:cnt+1=index成立且aheadOfAdd爲空,說明要插入的位置剛好在鏈表尾向後第二個位置
			//情況3:cnt+1=index單獨成立,說明找到了要插入的結點的前一個結點
		for (aheadOfAdd=head,cnt=1; aheadOfAdd!=null&&cnt+1<index; cnt++,aheadOfAdd=aheadOfAdd.next);
		//System.out.println(cnt);
		//System.out.println(aheadOfAdd);
		//情況1
		if (index != cnt+1) 
			return ;
		//情況2
		if (aheadOfAdd == null) 
			return ;

		//情況3
		aheadOfAdd.next = new Node(value, aheadOfAdd.next);
		length++;
		if (aheadOfAdd.next.next == null) tail = aheadOfAdd.next;
	}
		
	int deleteFromHead() {	//從鏈表頭刪除一個數據,返回被刪除的數據
		int deletedValue = -1;
		//鏈表爲空,直接返回
		if (head == null) 
			return -1;
		deletedValue = head.value;
		//鏈表只有一個元素,刪除並更新head和tail
		if (head == tail) 
			head = tail = null;
		//刪除頭部
		else 
			head = head.next;
		length--;
		return deletedValue;
	}
	int deleteFromTail() {	//從鏈表尾刪除一個數據,返回被刪除的數據
		int deletedValue = -1;
		//鏈表爲空,直接返回
		if (head == null)
			return -1;
		//鏈表只有一個元素,刪除並更新head和tail
		if (head == tail) {
			deletedValue = head.value;
			head = tail = null;
		}
		//刪除尾部
		else {
			Node now = null;
			//遍歷找到尾部
			for (now = head; now.next!=tail; now=now.next);
			deletedValue = now.next.value;
			now.next = null;
			tail = now;
		}
		length--;
		return deletedValue;
	}
	
	int deleteNode(int index) {	//刪除指定下標處的數據,返回被刪除的數據
		//下標不合法,直接返回
		if (index <= 0) return -1;
		int deletedValue = -1;
		int cnt = 1;
		Node now = null;
		//鏈表爲空,直接返回
		if (head == null) 
			return -1;
		//鏈表只有一個結點且要刪除那個結點
		if (head == tail && index == 1) {
			deletedValue = head.value;
			head = tail = null;
		}
		//如果要刪除第一個結點,那麼下方循環將會出現問題,所以單獨處理
		if (index == 1) {
			deletedValue = head.value;
			head = head.next;
		}
		else {
			//循環找到要刪除的那個結點
			//循環終止的條件有兩個
				//情況1:now==null成立,找到要刪除的結點之前已經到了鏈表尾
				//情況2:cnt+1=index成立,找到了要刪除的結點的前一個結點
			for(now=head; cnt+1<index && now!=null; cnt++,now=now.next);
			//情況1
			if(now == null) return -1; 
			//情況2
			deletedValue = now.next.value;
			if (now.next == tail)
				tail = now;
			now.next = now.next.next;
		}
		
		length--;
		return deletedValue;
		
	}
	//轉換爲字符串方便顯示
	public String toString() {
		StringBuilder sb = new StringBuilder("LinkedList: [");
		for (Node now = head; now!=null; now=now.next) {
			sb.append(now.value + ", ");
		}
		sb.append("]");
		if (head != null)
			sb.append("\n\t\t@ StartValue: " + head.value 
					+ "; TailValue: " + tail.value
					+ "; Length: " + length);
		return sb.toString();
	}
	
	//打印鏈表內容
	void printSelf() {
		System.out.println(this.toString());
	}
	
	//測試函數
	static public void main(String[] argv) {
		LinkedList list = new LinkedList();
		list.addToHead(1);list.addToHead(2);list.addToHead(5);list.printSelf();
		//list.deleteFromHead();list.deleteFromTail();list.printSelf();
		list.addNode(12, 1);list.printSelf();
		list.deleteNode(1);list.printSelf();
		//System.out.println(list.contains(5));
		//System.out.println(list.isEmpty());
	}
	
	
	
}
//鏈表的結點
class Node{
	int value;	//節點的值
	Node next;	//下一個結點的指針
	
	//兩個構造函數
	public Node(int value) {
		this.value = value;
		this.next = null;
	}
	public Node(int value, Node next) {
		this.value = value;
		this.next = next;
	}
}

 

發佈了86 篇原創文章 · 獲贊 59 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章