Java數據結構——靜態鏈表實現


Java數據結構——靜態鏈表實現

一、定義 
用數組描述的鏈表,即稱為靜態鏈表。 
在C語言中,靜態鏈表的表現形式即為結構體數組,結構體變量包括數據域data和游標CUR。(這里的定義來自於百度百科)

二、優點 
(1)這種存儲結構,仍需要預先分配一個較大的空間,但在作為線性表的插入和刪除操作時不需移動元素,僅需修改指針,故仍具有鏈式存儲結構的主要優點。 
(2)假如有如上的靜態鏈表S中存儲這線性表(a,b,c,d,f,g,h,i),Maxsize=11,如圖所示,要在第四個元素后插入元素e,方法是:先在當前表尾加入一個元素e,即:S[9].data = e;然后修改第四個元素的游標域,將e插入到鏈表中,即:S[9].cursor = S[4].cursor; S[4].cursor = 9;,接着,若要刪除第7個元素h,則先順着游標鏈通過計數找到第7個元素存儲位置6,刪除的具體做法是令S[6].cursor = S[7].cursor。

三、原理圖

例如一組數據如下:

(ZHAO,QIAN,SUN,LI,ZHOU,WU,ZHENG,WANG)

 

1 /**
2      * 靜態鏈表的長度
3      * @return
4      */
5     public int length(){
6         return size-1;
7     }

因為有個空表頭,所以長度為size-1;

 1 /**
 2      * 靜態鏈表的初始化
 3      */
 4     public StaticLinkList(){
 5         linkList = new Element[DEFAULT_SIZE];
 6         for (int i = 0; i < linkList.length; i++) {
 7             linkList[i] = new Element();
 8             linkList[i].data = -1;
 9             linkList[i].cur = i+1;
10         }
11         //當前空閑節點從1開始,因為第0個節點設置成了頭結點,設置為空,不
12         //存儲數據
13         currentFree = 1;
14     }

這里是不指定鏈表大小的鏈表初始化,默認長度為DEFAULT_SIZE,第8行為鏈表數據初始化,第9行初始化游標cur。

 1 /**
 2      * 給鏈表添加數據,每當鏈表滿了就給鏈表添加額外的空間
 3      * @param data
 4      */
 5     public void add(int data){
 6         if(size<linkList.length){
 7             linkList[currentFree].data = data;
 8             currentFree = linkList[currentFree].cur;
 9             size++;
10         }else{//鏈表已滿,給鏈表添加空間
11             addLinkSpace();
12             linkList[currentFree].data = data;
13             currentFree = linkList[currentFree].cur;
14             size++;
15         }
16     }

這個函數是給靜態鏈表添加數據,第6行判斷鏈表是否已滿,currentFree是指向當前空閑位置,第7行是將要添加的數據添加到空閑位置上,第8行currentFree指向下一個空閑位置,第9行鏈表實際長度加1,第11行,如果鏈表已滿,則給鏈表添加空間(addLinkSpace())。

 1 /**
 2      * 得到索引指定的數據
 3      * @param index
 4      * @return
 5      */
 6     public int get(int index){
 7         if(index>size-1&&index<0)
 8             throw new IndexOutOfBoundsException("數組越界,索引不合法");
 9         else{
10             //這里index+1也是因為多了一個空的頭節點
11             return linkList[index+1].data;
12         }
13     }

第11行index+1是因為鏈表的第一位為空,不取到第一位。

 1 /**
 2      * 刪除指定位置的節點
 3      * @param index
 4      */
 5     public void delete(int index){
 6 
 7         index = index+1;
 8         if(index<1||index>=size){
 9             System.out.println("超出鏈表長度");
10         }else if(index == size-1){
11             size--;
12             linkList = (Element[]) getTrueIndex(linkList,size);
13         }else{
14             int i = 0;
15             while(index!=linkList[i].cur){
16                 i++;
17             }
18             int j = 0;
19             while(currentFree!=linkList[j].cur){
20                 j++;
21             }
22             linkList[i].cur = linkList[index].cur;
23             linkList[j].cur = index;
24             linkList[index].cur = currentFree;
25             currentFree = index;
26             size--;
27             linkList = (Element[]) getTrueIndex(linkList,size);
28         }
29     }

第7行也是因為鏈表頭結點為空。第10行是指,如果刪除鏈表的最后一位,則執行下面的操作。第12行是將鏈表按照邏輯順序重新排列,是為了顯示。第14-17行是為了找到指向index的游標,如果沒有12行,則指向index的游標不一定是index-1,因為物理位置連續的,邏輯位置不一定連續。18-21行是為了找到指向當前空閑位置的游標,理由同上。22行是將原指向index的游標指向原index的游標指向的位置,23行是將原指向當前空閑位置的游標指向index,表明index為空閑,24行是將index的游標指向原當前空閑位置,25行是將當前空閑位置指向index。其他的都是差不多的,還有幾個函數就不一一介紹了。

 

 

四、完整代碼示例 
4.1 StaticLinkList.java

package com.yds.list;
/**
 * 因為靜態鏈表實質上是一維數組的存儲方式,所以它在物理位置上的存儲
 * 是順序的,但它是用游標來指向下一個數據的,所以根據它的下標來獲取數據
 * 和按照游標的指向來獲取數據是不同的,這里設置該鏈表的頭結點為空
 * @author Administrator
 *
 */
public class StaticLinkList {

    private Element[] linkList = null; 
//  private Element[] linkList1 = null;
    private int DEFAULT_SIZE = 4;//默認存儲大小
    private int currentFree = 0;//指向當前空閑位置
    private int size = 1;
    class Element{
        int data;
        int cur;
    }
    /**
     * 靜態鏈表的長度
     * @return
     */
    public int length(){
        return size-1;
    }
    /**
     * 靜態鏈表的初始化
     */
    public StaticLinkList(){
        linkList = new Element[DEFAULT_SIZE];
        for (int i = 0; i < linkList.length; i++) {
            linkList[i] = new Element();
            linkList[i].data = -1;
            linkList[i].cur = i+1;
        }
        //當前空閑節點從1開始,因為第0個節點設置成了頭結點,設置為空,不
        //存儲數據
        currentFree = 1;
    }
    /**
     * 給鏈表添加數據,每當鏈表滿了就給鏈表添加額外的空間
     * @param data
     */
    public void add(int data){
        if(size<linkList.length){
            linkList[currentFree].data = data;
            currentFree = linkList[currentFree].cur;
            size++;
        }else{//鏈表已滿,給鏈表添加空間
            addLinkSpace();
            linkList[currentFree].data = data;
            currentFree = linkList[currentFree].cur;
            size++;
        }
    }
    /**
     * 得到索引指定的數據
     * @param index
     * @return
     */
    public int get(int index){
        if(index>size-1&&index<0)
            throw new IndexOutOfBoundsException("數組越界,索引不合法");
        else{
            //這里index+1也是因為多了一個空的頭節點
            return linkList[index+1].data;
        }
    }
    /**
     * 刪除指定位置的節點
     * @param index
     */
    public void delete(int index){

        index = index+1;
        if(index<1||index>=size){
            System.out.println("超出鏈表長度");
        }else if(index == size-1){
            size--;
            linkList = (Element[]) getTrueIndex(linkList,size);
        }else{
            int i = 0;
            while(index!=linkList[i].cur){
                i++;
            }
            int j = 0;
            while(currentFree!=linkList[j].cur){
                j++;
            }
            linkList[i].cur = linkList[index].cur;
            linkList[j].cur = index;
            linkList[index].cur = currentFree;
            currentFree = index;
            size--;
            linkList = (Element[]) getTrueIndex(linkList,size);
        }
    }
    /**
     * 增加鏈表空間
     */
    public void addLinkSpace(){
        DEFAULT_SIZE+=8;
        Element[] link = linkList;
        linkList = new Element[DEFAULT_SIZE];
        System.arraycopy(link, 0, linkList, 0, link.length);
        for (int i = link.length; i < DEFAULT_SIZE; i++) {
            linkList[i] = new Element();
            linkList[i].data = -1;
            linkList[i].cur = i+1;
        }
        currentFree = link.length;
    }

    /**
     * 根據指定的位置插入數據
     * @param index
     * @param data
     */
    public void insert(int index,int data){
        //這里加1的原因是因為鏈表的第0位為空節點,這里設置的頭節點為空
        index = index + 1;
        if(size<linkList.length){
            if(index>size&&index<0)
                System.out.println("數組越界,超出數組長度");
            else if(index == size){
                linkList[currentFree].data = data;
                currentFree = linkList[currentFree].cur;
                size++;
            }else{
                /******未按邏輯順序排序而插入數據的寫法,因為未排序,則當前索引的上個節點的索引不一定是當前索引減1****/
                int i = 0;
                while(index!=linkList[i].cur){
                    i++;
                }
                int j = 0;
                while(currentFree!=linkList[j].cur){
                    j++;
                }
                linkList[i].cur = currentFree;
                linkList[j].cur = linkList[currentFree].cur;
                linkList[currentFree].data = data;
                linkList[currentFree].cur = index;
                currentFree = linkList[j].cur;
                size++;
                //每次插入后將鏈表按邏輯順序重新排序,是為了方便輸出查看。
                linkList = (Element[]) getTrueIndex(linkList,size);
            }
        }else{
            addLinkSpace();
            insert(index, data);
        }
    }
    /**
     * 按照邏輯順序重新排列
     * @param link 
     * @return
     */
    public Object getTrueIndex(Element[] link,int size){
        Element[] linkList1 = new Element[linkList.length];
        int k =0;
        for (int i = 0; i < linkList.length; i++) {
            linkList1[i] = new Element();
            linkList1[i].data = link[k].data;
            k = link[k].cur;
            linkList1[i].cur = i+1;
        }
        //插入時,currentFree肯定是最后一個了,但刪除后,currentFree就不一定是最后一位了
        currentFree = size;
        return linkList1;
    }
}

4.2 JavaMain.java

package com.yds.list;

public class JavaMain {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        StaticLinkList listA = new StaticLinkList();
        int la[]={
                2,3,5,8,9,6,7
        };
        for (int i = 0; i < la.length; i++) {
            listA.add(la[i]);
        }
        listA.delete(6);
        listA.delete(0);

        listA.insert(3, 88);
        listA.insert(3, 78);
        for (int i = 0; i < listA.length(); i++) {
            System.out.println(listA.get(i));
        }
    }

}

五、結果截圖 

 


免責聲明!

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



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