面向對象類的設計----LinkedBox類的封裝

數組有些地方不是很好 長度固定 頻繁添加元素 刪除元素 個數改變
利用面向對象的編程思想,設計一個類 LinkedBox,它的數據結構類似於鏈式存儲結構。

  • 最早 利用數組存儲一組元素
    長度固定 好處在於創建後不會浪費內存
    不好在於長度不變 添加刪除時個數的改變很麻煩
  • 自己可以設計類 ArrayBox
    點擊查看—>面向對象類的設計----ArrayBox類的封裝.
    長度看似可以改變 好處在於添加 刪除時不需要糾結長度變化的問題
    不好在於 插入 刪除效率低 不斷的移動元素的位置進行覆蓋
  • 再設計一個類 LinkedBox , 它是一個鏈表 ,鏈式結構的小容器。
    長度看似可以改變 解決了插入和刪除效率低的問題 不適合遍歷

LinkedBox類的封裝

首先,我們爲了統一規範,設計一個接口,將添加,獲取,刪除,獲取有效元素個數的這幾個常用方法的方法名(add get remove size)和使用方法(要什麼參數,返回值是什麼)進行統一。

public interface Box {
	public boolean add(int element);
	public int remove(int index);
	public int get(int index);
	public int size();
}

異常類BoxIndexOutOfBoundsException:

public class BoxIndexOutOfBoundsException extends RuntimeException{
	public BoxIndexOutOfBoundsException(){}
	public BoxIndexOutOfBoundsException(String msg){
		super(msg);
	}
}

Node類,該類定義了我們設計的工具類LinkedBox節點的數據結構:

public class Node {
	public Node prev;//previous  上一個node對象
	public int item;//當前數據
	public Node next;//下一個node對象
	public Node(Node prev,int item,Node next){
		this.prev = prev;
		this.item = item;
		this.next = next;
	}
}

LinkedBox類:

public class LinkedBox implements Box {
	private Node first;// 記錄頭節點
	private Node last;// 記錄尾節點
	private int size;// 記錄有效元素的個數

	// linkLast負責將元素添加在新的Node裏, 掛在鏈表的尾端
	private void linkLast(int element) {
		// 獲取鏈表的尾節點
		Node lNode = last;
		// 創建一個新的Node對象,將新數據包裝起來
		Node newNode = new Node(lNode, element, null);
		// 將新節點對象設置爲尾節點
		last = newNode;
		// 需要做一個嚴謹的判斷
		if (lNode == null) {// 如果原來尾節點沒有對象,證明這個鏈表沒有使用過
			first = newNode;// 將這個新節點設置爲頭節點
		} else {
			lNode.next = newNode;
		}
		// 有效元素個數增加一個
		size++;
	}
	//負責檢測index的合法性
	private void rangeCheck(int index) {
		if(index<0 || index>=size){
			throw new BoxIndexOutOfBoundsException("Index:"+index+", Size:"+size);
		}
	}
	//負責找尋給定index位置的node對象
	private Node findNode(int index){
		Node targetNode;//用來存儲找到的node對象
		//判斷index範圍是在前半部分,還是在後半部分
		if(index<(size>>1)){
			//index比size的一半還要小,證明在前半部分,從前往後找比較快
			targetNode = first;
			for(int i = 0;i<index;i++){
				targetNode = targetNode.next;
			}
		}else{//從後往前找
			targetNode = last;
			for (int i = size-1; i > index; i--) {
				targetNode = targetNode.prev;
			}
		}
		return targetNode;
	}
	//負責將給定的node節點對象刪除,並且保留所刪除的數據
	private int unLink(Node targetNode){
		//獲取當前node的item值
		int oldValue = targetNode.item;
		//當前node的前一個
		Node prev = targetNode.prev;
		//當前node的下一個
		Node next = targetNode.next;
		//刪除節點對象
		if(prev == null){//當前節點是頭節點
			first = next;//讓下一個節點變成頭節點
		}else{
			prev.next = next;
			//讓targetNode對象的prev指向空
			targetNode.prev = null;
		}
		if(next == null){//當前節點是尾節點
			last = prev;//讓它前一個變成尾節點
		}else{
			next.prev = prev;
			//讓targetNode對象的next指向空
			//讓後targetNode即可以被回收
			targetNode.next = null;
		}
		//讓有效元素個數減少一個
		size--;
		return oldValue;
	}
	// ----------------------------------------------
	@Override
	public boolean add(int element) {
		//將element存入一個新的Node對象裏,添加至鏈表的尾端
		this.linkLast(element);
		//告知添加成功
		return true;
	}

	@Override
	public int remove(int index) {
		// 檢測index是否合法
		this.rangeCheck(index);
		//找尋index對應位置的那個node對象
		Node targetNode = this.findNode(index);
		//需要將當前節點的前一個元素的next指向當前節點的下一個元素,當前節點的後一個元素的prev指向當前節點的前一個元素
//		targetNode.prev.next = targetNode.next;
//		targetNode.next.prev= targetNode.prev;
		int oldValue = this.unLink(targetNode);
		return oldValue;
	}

	@Override
	public int get(int index) {
		// 檢測index是否合法
		this.rangeCheck(index);
		//找尋index對應位置的那個node對象,然後再將node對象中封裝的數據取出來
		Node targetNode = this.findNode(index);
		//返回找到的Node對象內的數據
		return targetNode.item;
	}

	@Override
	public int size() {
		return size;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章