Java入門——自己寫的LinkedList的增刪查改方法

昨天寫了簡單的自己的ArrayList類,今天寫寫LinkedList類。(因爲懶惰,原理就不寫了)

使用一個自己寫的結點類(包含了數據域和引用域)來實現相關操作。

 

構造MyLinkedList類

先寫結點類:

package MyLinkedList;

public class Node {
	private Object data; //數據域
	private Node next; //引用,指向下一個結點
	
	//構造方法
	public Node() {
		// TODO Auto-generated constructor stub
		
	}
	//構造方法:傳入數據,置空next
	public Node(Object data) {
		this.data = data;
		this.next = null;
	}

	public Object getData() {
		return data;
	}
	public void setData(Object data) {
		this.data = data;
	}
	public Node getNext() {
		return next;
	}
	public void setNext(Node next) {
		this.next = next;
	}
	
}

然後就可以構造鏈表類了

package MyLinkedList;

public class MyLinkedList {
	private Node head; // 頭結點
	private Node last; // 尾結點
	private int size; // 結點長度

	/**
	 * 構造方法:初始化頭結點和尾結點
	 */
	MyLinkedList() {
		head = new Node();
		last = head; // 初始狀態頭結點與尾結點指向同一個結點
	}

	
}

重寫一個toString()方法

/**
	 * 規範鏈表輸出格式
	 */
	public String toString() {
		StringBuffer sb = new StringBuffer();
		Node current = head; // 從頭結點開始遍歷
		while (true) {
			if (current.getNext() != null) {// 不是最後一個結點時(next域不爲空)
				current = current.getNext(); // 先指向下一個結點(因爲頭結點的數據爲空)
				sb.append(current.getData()); // 取出數據
				// 添加分隔符號
				sb.append("->");
			} else {
				// 遍歷完了之後,退出循環
				break;
			}
		}
		// 去除最後一個分隔符
		sb.deleteCharAt(sb.length() - 1);
		sb.deleteCharAt(sb.length() - 1);
		return sb.toString();
	}

 

添加操作add()

我重載了兩個添加操作的方法,一個是直接添加數據到鏈表尾部;另一個是在保證不越界的情況下,可以往鏈表的中間位置插入結點。

第一個添加操作:

/**
	 * 增加操作
	 * 
	 * @param obj 要添加的結點數據
	 */
	public void add(Object obj) {
		// 先創建一個結點
		Node node = new Node(obj);
		// 把新建的結點加入到鏈表中
		last.setNext(node);
		// 更改last的指向
		last = node;
		// 更改結點長度
		size++;
	}

查看效果:

package MyLinkedList;

public class TestMyLinkedList {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		//創建鏈表
		MyLinkedList myInt =new MyLinkedList();
		myInt.add(1);
		myInt.add(2);
		myInt.add(3);
		myInt.add("a");
		System.out.println(myInt.toString());
		
	}

}

注:因爲類中數據類型爲Object,可以爲任何類型的數據,且一個鏈表中數據類型可以多樣。

若想要鏈表數據類型任意但是統一,可以使用泛型。

第二種添加操作(插入)

/**
	 * 插入操作
	 * 
	 * @param desIndex 插入的目標位置下標
	 * @param obj      插入的結點數據
	 */
	public void add(int desIndex, Object obj) {
		// 判斷下標是否合法
		if (desIndex < 0 || desIndex > size+1) { //(+1是因爲,允許插入到尾部)
			try {
				throw new Exception("下標越界");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} else {
			// 其他地方可以正常插入,先創建一個結點
			Node node = new Node(obj);
			// 插入到頭結點後一個位置
			if (desIndex == 0) {
				// 先把新結點的next指向原本頭結點指向的位置
				node.setNext(head.getNext());
				// 使頭結點的next指向新建立的結點
				head.setNext(node);
				// size增加
				size++;
			}
			// 其他位置
			else {
				// 首先需要從頭遍歷找到要插入位置的前一個結點
				Node before = head;
				for (int i = 0; i < desIndex; i++) {
					before = before.getNext();
				}
				// 循環結束,找到了before的位置
				// 先把新建的結點的next指向before的next結點
				node.setNext(before.getNext());
				// 將before的next指向新創建的結點
				before.setNext(node);

				// 若創建的結點是最後一個,需要重新設置last
				if (desIndex == size) {
					last = node;
				}
			}
		}

	}

效果查看:

異常測試:

 

刪除操作remove()

刪除操作重載了兩個,一個是根據下標進行刪除,一個是傳入值,找到該值進行刪除

根據下標刪除:

/**
	 * 刪除操作
	 * 
	 * @param desIndex 需要刪除的結點位置
	 */
	public void remove(int desIndex) {
		// 判斷位置下標是否合法
		if (desIndex < 0 || desIndex > size) {
			try {
				throw new Exception("下標越界");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		else {
			Node before = head; // 需要刪除的前一個結點
			// 先找到before結點的位置
			for (int i = 0; i < desIndex; i++) {
				before = before.getNext();
			}
			// 循環結束,找到了before的位置
			// 將before的next指向要刪除的下一個
			before.setNext(before.getNext().getNext());
			// 將要刪除的結點的next置空
			// before.getNext().setNext(null);
			// size減少
			size--;

			// 若刪除的是最後一個結點,需要更改last
			if (desIndex == size) {
				last = before.getNext();
			}
		}
	}

效果查看:

第二種,根據值查找刪除(其中使用到的search查找方法是自己寫的,在下一個部分)

/**
	 * 刪除操作
	 * @param obj 需要刪除的結點數據
	 */
	public void remove(Object obj) {
		// 獲得要刪除的元素位置下標
		int index = search(obj);
		if (index != -1) {
			// 直接調用前面的方法
			remove(index);
		} else {
			System.out.println("沒有找到你要刪除的元素");
		}
	}

效果查看:

myInt.remove((Integer)3); 

異常測試:

 

查找操作search()

在鏈表中查找某數據,返回位置下標。若沒有找到,返回-1

/**
	 * 查找操作
	 * 
	 * @param obj 需要查找的結點數據
	 * @return 返回結點位置下標。若沒有找到,返回-1
	 */
	public int search(Object obj) {
		int index = -1; // 記錄下標
		Node node = head;
		// 遍歷鏈表進行查找
		for (int i = 0; i < size; i++) {
			node = node.getNext();
			// 判斷
			if (node.getData() == obj) {
				index = i;
				break; // 退出循環
			}
		}
		return index;
	}

效果:

System.out.println(myInt.search(3));

 

修改操作set()

修改也重載了兩個。一個根據下標修改,一個根據原始值查找修改。

根據下標修改:

/**
	 * 更改操作
	 * @param desIndex 需要更改的結點位置下標
	 * @param obj 需要更改的結點新數據
	 */
	public void set(int desIndex, Object obj) {
		// 判斷位置下標是否合法
		if (desIndex < 0 || desIndex > size) {
			try {
				throw new Exception("下標越界");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		else {
			Node node=head; //獲得要刪除的結點
			//遍歷獲得
			for(int i=0;i<=desIndex;i++) {
				node=node.getNext();
			}
			//更改數據
			node.setData(obj);
		}
		
	}
	

效果:

根據值查找修改:

 

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