數組有些地方不是很好 長度固定 頻繁添加元素 刪除元素 個數改變
利用面向對象的編程思想,設計一個類 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;
}
}