线性表链式存储结构Java实现

线性表、链式存储结构

线性表是相对于逻辑结构,链式存储结构是相对于物理存储。即逻辑上是一个接一个,物理存储上是随机的。

链式存储的特点

关键字

头结点、尾结点、数据域、指针

特点

头结点:数据域为空,指针指向第一个结点
尾结点:数据与不为空,指针指向空

Java代码实现

查询

类结构:

  • MyLink
  • SelectLinkList
  • SelectLinkListTest
    MyLink是用来构造链式存储对象、SelectLinkList用来查询出指定位置的对象、SelectLinkListTest是测试

代码实现

MyLink.java

public class MyLink {
    /**
     * 数据域
     */
    private int data;
    /**
     * 所指向的下一个对象的地址
     */
    private MyLink nextLink;

    public MyLink() {
    }

    public MyLink(MyLink nextLink) {
        this.nextLink = nextLink;
    }

    public MyLink(int data, MyLink nextLink) {
        this.data = data;
        this.nextLink = nextLink;
    }

    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }

    public MyLink getNextLink() {
        return nextLink;
    }

    public void setNextLink(MyLink nextLink) {
        this.nextLink = nextLink;
    }
}

SelectLinkList.java

public class SelectLinkList {
    /**
     * 用来帮助循环构建MyLink对象
     */
    private MyLink[] links;
    /**
     * 假定传入MyLink[10],即要创建10个MyLink对象。这10个对象中是不应该包含头节点的。
     * 因为传入的数组中,所有位置都要包含数据;而MyLink的对象中头节点的构造方法是
     * MyLink(MyLink nextLink),所以在这里拿出来。
     */
    private MyLink myLinkHeader = null;

    /**
     * 为了传入自定义MyLink[]的长度
     * @param links
     */
    public SelectLinkList(MyLink[] links) {
        this.links = links;
    }

    /**
     * 循环构建MyLink对象。
     * @return
     */
    public void createLink() {
        //拿到长度,知道构造的节点是从哪里开始
        int a = links.length;
        //链式结构中除了尾节点,其他节点必须包含当前对象所指向下一个对象的地址,
        //那么构造时就必须知道后一个节点的位置,所以必须从后往前构造。先构造最后一个结点。
        links[a - 1] = new MyLink(a, null);
        //循环构造MyLink对象,i=a-1相对于长度(个数)来说是倒数第二,所以其中links[i-1]就表示倒数第二位的元素
        //,从后往前构造到links[0],头节点需要自己手动构造。i相对于长度,所以links[0]对应i就是1,
        //也就是说只能循环到i=1
        for (int i = a - 1; i >= 1; i--) {
            links[i - 1] = new MyLink(i, links[i]);
        }
        //构造头节点,指向数组第一个元素
        myLinkHeader = new MyLink(links[0]);
    }

    /**
     * 查出传入k位置的数据域和下一个节点的地址
     * @param k
     * @return
     */
    public MyLink getLink(int k) throws Throwable {
        if (k<1 || k>links.length) {
            throw new Throwable("查询位置不合理");
        }
        //k是查找出k位置的元素,j是开始计数的位置;0是因为会多出一个头节点,先从头开始,头不计入查找的数组。
        int j = 0;
        //用一个MyLink对象来不断接收被重新赋对象。它先指向头
        MyLink myLink = myLinkHeader;
        //从头开始找,直到
        while (j < k) {
            myLink = myLink.getNextLink();
            j++;
        }
        return myLink;
    }
}

SelectLinkListTest.java

public class SelectLinkListTest {
    public static void main(String[] args) {
        //循环构造myLink
        MyLink[] myLinks = new MyLink[10];
        SelectLinkList selectLinkList = new SelectLinkList(myLinks);
        selectLinkList.createLink();
        //获取k位置的数据域中的数据
        MyLink link;
        try {
            link = selectLinkList.getLink(6);
            System.out.println("获取的数值域中数据为:" + link.getData());
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }
}

结果

结果应该是:


image.png

如果输入的getLink()参数不满足条件:


image.png

插入

其特点是,在i位置插入,插入元素的指针指向原来i位置指针指向的元素,那么将原来i-1位置的元素的指针改为指向插入的元素。
类结构:

  • InsertLinkList.java
  • InsertLinkListTest.java
    InsertLinkList构造线性表链式存储结构,并提供插入和查询方法;InsertLinkListTest测试。

代码实现

InsertLinkList

public class InsertLinkList {
    /**
     * 用来帮助循环构建MyLink对象
     */
    private MyLink[] links;
    /**
     * 假定传入MyLink[10],即要创建10个MyLink对象。这10个对象中是不应该包含头节点的。
     * 因为传入的数组中,所有位置都要包含数据;而MyLink的对象中头节点的构造方法是
     * MyLink(MyLink nextLink),所以在这里拿出来。
     */
    private MyLink myLinkHeader = null;

    /**
     * 为了传入自定义MyLink[]的长度
     * @param links
     */
    public InsertLinkList(MyLink[] links) {
        this.links = links;
    }

    /**
     * 循环构建MyLink对象。
     * @return
     */
    public void createLink() {
        //拿到长度,知道构造的节点是从哪里开始
        int a = links.length;
        //链式结构中除了尾节点,其他节点必须包含当前对象所指向下一个对象的地址,
        //那么构造时就必须知道后一个节点的位置,所以必须从后往前构造。先构造最后一个结点。
        links[a - 1] = new MyLink(a, null);
        //循环构造MyLink对象,i=a-1相对于长度(个数)来说是倒数第二,所以其中links[i-1]就表示倒数第二位的元素
        //,从后往前构造到links[0],头节点需要自己手动构造。i相对于长度,所以links[0]对应i就是1,
        //也就是说只能循环到i=1
        for (int i = a - 1; i >= 1; i--) {
            links[i - 1] = new MyLink(i, links[i]);
        }
        //构造头节点,指向数组第一个元素
        myLinkHeader = new MyLink(links[0]);
    }

    /**
     * 在i位置屁股后面插入myLink对象
     * @param myLink
     * @param i
     */
    public void insertLink(MyLink myLink,int i) {
        MyLink myLinkMove = myLinkHeader.getNextLink();
        if (i == 0) {
            //在头位置插入myLink对象,让myLink对象指向头指针指向的对象,头结点指向myLink对象
            myLink.setNextLink(myLinkMove);
            myLinkHeader.setNextLink(myLink);
        }else if (i>=1 && i<links.length-1){
            //遍历获取到插入位置i的myLink对象
            for (int k = 1; k < i ; k++) {
                myLinkMove = myLinkMove.getNextLink();
            }
            //获取i位置的没有Link对象的下一对象
            MyLink myLink2 = myLinkMove.getNextLink();
            //插入的对象的指针为原来位置指向下一结点的指针
            myLink.setNextLink(myLink2);
            //将插入位的对象的指针设置为要插入的对象
            myLinkMove.setNextLink(myLink);
        }else {
            //插入的位置超出或等于长度时,获取到末尾结点,让末尾结点的指针执行myLink对象
            MyLink myLinkLast = links[links.length-1];
            myLinkLast.setNextLink(myLink);
        }

    }


    /**
     * 查出传入k位置的数据域和下一个节点的地址
     * @param k
     * @return
     */
    public MyLink getLink(int k) throws Throwable {
        if (k<1 || k>links.length+1) {
            throw new Throwable("查询位置不合理");
        }
        //k是查找出k位置的元素,j是开始计数的位置;0是因为会多出一个头节点,先从头开始,头不计入查找的数组。
        int j = 0;
        //用一个MyLink对象来不断接收被重新赋对象。它先指向头
        MyLink myLink = myLinkHeader;
        //从头开始找,直到
        while (j < k) {
            myLink = myLink.getNextLink();
            j++;
        }
        return myLink;
    }
}

InsertLinkListTest

public class InsertLinkListTest {
    public static void main(String[] args) {
        //循环构造myLink
        MyLink[] myLinks = new MyLink[10];
        InsertLinkList insertLinkList = new InsertLinkList(myLinks);
        insertLinkList.createLink();
        //插入
        MyLink myLink = new MyLink(19,null );
        insertLinkList.insertLink(myLink, 2);
        try {
            MyLink link = insertLinkList.getLink(3);
            System.out.println(link.getData());
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }
}

结果

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345