zoukankan      html  css  js  c++  java
  • 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));
            }
        }
    
    }

    五、结果截图 

  • 相关阅读:
    crowd在更改IP后无法登录的问题
    VMware虚拟机中为Linux 添加虚拟硬盘(VirtualBox方法类似)
    虚拟机virtualbox中挂载新硬盘
    下载谷歌浏览器(Chrome)扩展离线安装包crx文件最简单的方法
    Chrome神器Vimium快捷键学习记录
    Chrome好用的扩展插件
    虚拟内存,MMU/TLB,PAGE,Cache之间关系
    ARM“庖丁解牛”之存储器管理单元MMU
    MMU——存储器管理单元
    我的vim配置---jeffy-vim-v2.3.tar
  • 原文地址:https://www.cnblogs.com/ityizhainan/p/6004964.html
Copyright © 2011-2022 走看看