實現個單向鏈表
包含:
(1)包含一個Node類型的成員變量first:用來記錄第一個結點的地址
如果這個鏈表是空的,還沒有任何結點,那麼first是null。
最後一個結點的特徵:就是它的next是null
(2)內部使用一個total,記錄實際存儲的元素的個數
(3)使用了一個內部類Node
private class Node{
Object data;
Node next;
}
public class SingleLinkedList {
//這裏不需要數組,不需要其他的複雜的結構,我只要記錄單向鏈表的“頭”結點
private Node first;//first中記錄的是第一個結點的地址
private int total;//這裏我記錄total是爲了後面處理的方便,例如:當用戶獲取鏈表有效元素的個數時,不用現數,而是直接返回total等
/*
* 內部類,因爲這種Node結點的類型,在別的地方沒有用,只在單向鏈表中,用於存儲和表示它的結點關係。
* 因爲我這裏涉及爲內部類型。
*/
private class Node{
Object data;//因爲數據可以是任意類型的對象,所以設計爲Object
Node next;//因爲next中記錄的下一個結點的地址,因此類型是結點類型
//這裏data,next沒有私有化,是希望在外部類中可以不需要get/set,而是直接“結點對象.data","結點對象.next"使用
Node(Object data, Node next){
this.data = data;
this.next = next;
}
}
public void add(Object obj){
/*
* (1)把obj的數據,包裝成一個Node類型結點對象
* (2)把新結點“鏈接”當前鏈表的最後
* ①當前新結點是第一個結點
* 如何判斷是否是第一個 if(first==null)說明暫時還沒有第一個
* ②先找到目前的最後一個,把新結點鏈接到它的next中
* 如何判斷是否是最後一個 if(某個結點.next == null)說明這個結點是最後一個
*/
// (1)把obj的數據,包裝成一個Node類型結點對象
//這裏新結點的next賦值爲null,表示新結點是最後一個結點
Node newNode = new Node(obj, null);
//①當前新結點是第一個結點
if(first == null){
//說明newNode是第一個
first = newNode;
}else{
//②先找到目前的最後一個,把新結點鏈接到它的next中
Node node = first;
while(node.next != null){
node = node.next;
}
//退出循環時node指向最後一個結點
//把新結點鏈接到它的next中
node.next = newNode;
}
total++;
}
public int size(){
return total;
}
public Object[] getAll(){
//(1)創建一個數組,長度爲total
Object[] all = new Object[total];
//(2)把單向鏈表的每一個結點中的data,拿過來放到all數組中
Node node = first;
for (int i = 0; i < total; i++) {
// all[i] = 結點.data;
all[i] = node.data;
//然後node指向下一個
node = node.next;
}
//(3)返回數組
return all;
}
public void remove(Object obj){
if(obj == null){
//(1)先考慮是否是第一個
if(first!=null){//鏈表非空
//要刪除的結點正好是第一個結點
if(first.data == null){
//讓第一個結點指向它的下一個
first = first.next;
total--;
return;
}
//要刪除的不是第一個結點
Node node = first.next;//第二個結點
Node last = first;
while(node.next!=null){//這裏不包括最後一個,因爲node.next==null,不進入循環,而node.next==null是最後一個
if(node.data == null){
last.next = node.next;
total--;
return;
}
last = node;
node = node.next;
}
//單獨判斷最後一個是否是要刪除的結點
if(node.data == null){
//要刪除的是最後一個結點
last.next = null;
total--;
return;
}
}
}else{
//(1)先考慮是否是第一個
if(first!=null){//鏈表非空
//要刪除的結點正好是第一個結點
if(obj.equals(first.data)){
//讓第一個結點指向它的下一個
first = first.next;
total--;
return;
}
//要刪除的不是第一個結點
Node node = first.next;//第二個結點
Node last = first;
while(node.next!=null){//這裏不包括最後一個,因爲node.next==null,不進入循環,而node.next==null是最後一個
if(obj.equals(node.data)){
last.next = node.next;
total--;
return;
}
last = node;
node = node.next;
}
//單獨判斷最後一個是否是要刪除的結點
if(obj.equals(node.data)){
//要刪除的是最後一個結點
last.next = null;
total--;
return;
}
}
}
}
public int indexOf(Object obj){
if(obj == null){
Node node = first;
for (int i = 0; i < total; i++) {
if(node.data == null){
return i;
}
node = node.next;
}
}else{
Node node = first;
for (int i = 0; i < total; i++) {
if(obj.equals(node.data)){
return i;
}
node = node.next;
}
}
return -1;
}
}
TestSingleLinkedList.java
import java.util.Arrays;
public class TestSingleLinkedList {
public static void main(String[] args) {
SingleLinkedList list = new SingleLinkedList();
list.add("張三");
list.add("李四");
list.add("王五");
list.add("趙六");
list.add("錢七");
System.out.println("元素個數:" + list.size());//元素個數:5
Object[] all = list.getAll();
System.out.println(Arrays.toString(all));//[張三, 李四, 王五, 趙六, 錢七]
/*list.remove("張三");
System.out.println("元素個數:" + list.size());
all = list.getAll();
System.out.println(Arrays.toString(all));
list.remove("王五");
System.out.println("元素個數:" + list.size());
all = list.getAll();
System.out.println(Arrays.toString(all));
list.remove("錢七");
System.out.println("元素個數:" + list.size());
all = list.getAll();
System.out.println(Arrays.toString(all));*/
System.out.println(list.indexOf("張三"));//0
System.out.println(list.indexOf("王五"));//2
System.out.println(list.indexOf("錢七"));//4
}
}
記錄 - 搞定Java核心技術