Java實現單鏈表


一、分析

  單鏈表是一種鏈式存取的數據結構,用一組地址任意的存儲單元存放線性表中的數據元素。鏈表中的數據是以結點來表示的,每個結點由元素和指針構成。在Java中,我們可以將單鏈表定義成一個類,單鏈表的基本操作即是類的方法,而結點就是一個個實例化的對象,每個對象中都有“元素值”和“下一結點地址”兩個屬性。在“下一結點地址”屬性中存儲的是下一個對象的引用,這樣,一個個對象連在一起就成為了單鏈表。

  單鏈表有以下基本操作:

    1、初始化單鏈表

    2、銷毀單鏈表

    3、清空單鏈表

    4、檢測單鏈表是否為空

    5、返回單鏈表的元素個數

    6、返回單鏈表中指定位置元素的值

    7、返回單鏈表中第一個與指定值相同的元素的位置

    8、返回指定元素的直接前驅

    9、返回指定元素的直接后繼

    10、向指定位置插入元素

    11、刪除指定位置的元素

    12、遍歷單鏈表

  為了方便對單鏈表進行操作,我們還需要引入一個頭結點,頭結點中不存儲元素值,只存儲單鏈表第一個結點的地址。初始化單鏈表即創建頭結點,而銷毀單鏈表即銷毀頭結點。

二、實現

1、定義類屬性和構造函數

 1 class InitList{
 2     
 3     private int [] data = new int[1];   //用來存儲元素值,之所以用數組而不用整型,是為了用null來表示頭結點
 4     
 5     private InitList nextList;       //下一結點地址
 6     
 7     public InitList() {           //創建頭結點的構造函數
 8         this.data = null;
 9         this.nextList = null;
10     }
11     
12     public InitList(int data) {      //創建普通結點的構造函數
13         this.data[0] = data;
14         this.nextList = null;
15     }
16 }

2、清空單鏈表

1 public void clearList() {
2     this.nextList = null;          //將頭結點的下一結點地址(即單鏈表的第一個結點的地址)置空,則單鏈表會因缺少引用而被jvm回收,實現清空
3 }

3、檢測單鏈表是否為空

1 public boolean listEmpty() {
2     if(this.nextList == null) {      //通過判斷頭結點的下一結點地址是否為空,即可判斷單鏈表是否為空
3         return true;
4     }
5     return false;
6 }

4、返回單鏈表的元素個數

 1 public int listLength() {
 2 
 3     InitList theList = this.nextList;        //獲取頭結點的下一結點地址
 4     int i = 0;                         //計數器初始化
 5 
 6     for (i = 0; theList != null; i++) {      //循環判斷結點地址是否為空,如果不為空,則表明存在結點,計數器i加一;如果為空,則表明已到達單鏈表尾部,退出循環
 7         theList = theList.nextList;         //取下一結點進行判斷
 8     }
 9     return i;                      //返回計數器的值
10 }

5、返回單鏈表中指定位置元素的值

 1 public int [] getElem(int site) {
 2 
 3     if(site < 1) {                      //判斷輸入的位置是否合法
 4         return null;
 5     }
 6 
 7     InitList theList = this;              //得到頭結點的地址
 8 
 9     for (int i = 0; i < site; i++) {        //循環讀取結點,直到指定的位置
10         theList = theList.nextList;        //獲取下一結點的地址
11         if(theList == null) {            //如果下一結點地址為空,則表明已經到達單鏈表末尾,指定的位置超出了單鏈表的長度
12             return null;              //未取到元素,返回null
13         }
14     }
15     return theList.data;              //返回指定位置元素值
16 }

6、返回單鏈表中第一個與指定值相同的元素的位置

 1 public int locateElem(int value) {
 2 
 3     InitList theList = this.nextList;
 4 
 5     for(int i = 1; theList != null; i++) {     //如果取得的結點不為空,執行循環
 6         if(theList.data[0] == value) {        //比較結點值與給定的值是否相等
 7             return i;                  //相等返回結點位置
 8         }
 9         theList = theList.nextList;         //取下一結點地址
10     }
11 
12     return 0;                      //未找到則返回零
13 }

7、返回指定元素的直接前驅

 1 public int [] priorElem(int value) {
 2 
 3     InitList theList = this.nextList;
 4 
 5     if(theList == null) {                    //如果頭結點的下一結點為空,則表明單鏈表為空,返回null
 6         return null;
 7     }
 8 
 9     InitList theNextList = this.nextList.nextList;     //獲取單鏈表的第二個結點
10     int [] ret = new int[this.listLength()];         //創建一個與單鏈表長度相同的數組,用來存儲找到的直接前驅的值
11     int i = 1;                           //計數器
12 
13     while (theNextList != null) {               //因為單鏈表的第一個結點沒有直接前驅,因此從第二個結點開始循環
14         if(theNextList.data[0] == value) {         //如果與給定值相等,則取得其前驅,計數器加一
15             ret[i] = theList.data[0];
16             i++;
17         }
18         theList = theNextList;                //取下一地址,准備下一循環
19         theNextList = theNextList.nextList;
20     }
21 
22     if(i == 1) {                        //i為1表明未取到直接前驅
23         return null;
24     }
25 
26     ret[0] = i - 1;                      //將計數器的值存入數組第0位
27     return ret;
28 }

8、返回指定元素的直接后繼

 1 public int [] nextElem(int value) {              //與獲取直接前驅類似,這里不再贅述
 2 
 3     InitList theList = this.nextList;
 4 
 5     if(theList == null) {
 6         return null;
 7     }
 8 
 9     InitList theNextList = this.nextList.nextList;
10     int [] ret = new int[this.listLength()];
11     int i = 1;
12 
13     while (theNextList != null) {
14         if(theList.data[0] == value) {
15             ret[i] = theNextList.data[0];
16             i++;
17         }
18         theList = theNextList;
19         theNextList = theNextList.nextList;
20     }
21 
22     if(i == 1) {
23         return null;
24     }
25 
26     ret[0] = i - 1;
27     return ret;
28 }

9、向指定位置插入元素

 1 public boolean listInsert(int site,int value) {
 2 
 3     if(site < 1) {                        //判斷指定位置是否合法
 4         return false;
 5     }
 6
7
   InitList list = new InitList(value); 8 InitList theNextList = this; 9 InitList theList = null; 10 11 for(int i = 0; i < site; i++) {             //循環讀取到指定位置 12 theList = theNextList; 13 if(theList == null) {                //如果為空,表示已到單鏈表末尾,返回false 14 return false; 15 } 16 theNextList = theNextList.nextList; 17 } 18 19 list.nextList = theNextList;                //將新結點插入指定位置中 20 theList.nextList = list; 21 return true; 22 }

10、刪除指定位置的元素

 1 public boolean listDelete(int site) {
 2 
 3     InitList theList = this;
 4     InitList theNextList = this.nextList;
 5 
 6     if(site < 1 || theNextList == null) {        //判斷指定位置是否合法和單鏈表是否為空
 7         return false;
 8     }else if(site == 1) {                  //如果要刪除的是第一個結點,則直接刪除
 9         theList.nextList = theNextList.nextList;
10         return true;
11     }
12 
13     for(int i = 1; i < site; i++) {            //循環讀取到指定位置
14         theNextList = theNextList.nextList;
15         if(theNextList == null) {
16             return false;
17         }
18         theList = theList.nextList;
19     }
20 
21     theList.nextList = theNextList.nextList;       //刪除指定位置的結點
22     return true;
23 }

11、遍歷單鏈表

 1 public String traverseList() {          //這里通過輸出單鏈表來表示遍歷
 2 
 3     InitList theList = this.nextList;
 4     String s = "";                 //用來存儲單鏈表的值
 5 
 6     while(theList != null) {           //循環獲取結點值
 7         s += theList.data[0] + "、";
 8         theList = theList.nextList;
 9     }
10 
11     if(s.length() == 0) {             //如未獲取到值,直接返回s
12         return s;
13     }
14 
15     return s.substring(0,s.length() - 1);   //去除最后的頓號后返回
16 }

三、小結

  以上就是單鏈表用Java的實現,由於只定義了整數的數組,因此只能操作整數數據,但單鏈表的基本思想都已實現。

四、糾正

  隔了一段時間又回來看代碼,猛地發現這段代碼其實還不夠完善。(⊙x⊙;)

  將單鏈表的基本操作定義成了InitList類的方法,實例化結點時,會使每個結點都擁有這些方法,然而其實只有頭結點需要這些方法,其他結點都不需要。

  因此可以將InitList類定義成頭節點類,而其他節點定義成頭節點的內部類,這樣,就只有頭節點可以操作其他節點。

  由於要修改的地方太多,這里我就不修改了,放在這里提醒自己。(就是因為懶……(><))


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM