数据结构学习笔记(03单链表)

单链表是什么

【代码文件看末尾】

单链表是一种相对于线性表的一种存储方式,在线性表中我需要对我们的数据大小进行预先的评判,来给出我们的存储空间,这样会出现一个问题,我们无法预先确定数据的大小,如果我们的数据量比较小,但是默认开辟了很多空间,那么就造成了资源的浪费,那如果我们数据量很大而开辟空间不足,也不能满足我们的需求,而且对于线性表来说我们插入或者删除其中的元素会造成大量元素的移动,并且我们使用算法对线性表进行拓展空间的时候也会大量移动元素才能完成操作,所以相对的我们出现了链表的概念,什么是链表呢?

相对于线性表中存储的元素在物理地址中是连续的不同,我们的链表在屋里存储中是分散的,可能第一个元素在46号内存地址,第二个就在558号地址,为了使不同地址的元素之间能找到彼此,我们的每一个数据节点在存储数据的本身的情况下还需要存储下一个元素的指针,因为在java中不存在显示的指针,所以我们通过对象的应勇来访问下一个数据节点就行了。这样一环扣一环就形成了一个链条,也就是单链表


单链表图示

在单链表,我们需要首先构造一个Node类来表示每一个节点

每一个节点我们设计一个数据域(存储数据的属性)一个指针域(存储下一个对象)

class Node<dataType>{

    private dataType  nodeData;//构造数据域

    private Node next;//指针,存储下一个数据节点的引用

}

这样我们就构造好了一个节点,为了规范引用,我们封装成一个JavaBean的样子,不直接操作属性,通过方法来操作。

class Node<dataType>{

    private dataType  nodeData;//构造数据域

    private Node next;//指针,存储下一个数据节点的引用

    public Node(dataType nodeData) //构造函数,新建一个节点可以没有下一个节点的指针但是必须要存数据吧~

        this.nodeData = nodeData;

    }

    public Node getNext() {//获取下一个数据节点

        return next;

    }

    public dataType getNodeData() {//获取当前节点存储的数据

        return nodeData;

    }

    public void setNext(Node next) {//设置下一个节点

        this.next=next;

    }

    public void setNodeData(dataType nodeData) {//设置当前节点的数据

        this.nodeData=nodeData;

    }

}


这样我们的一个Node节点就构造好了,我们指定了泛型,可以存储我们指定的数据~


有了节点我们就可以构造链表了,对于链表我们有两个基本的玩意儿就是头节点,因为我们需要一个头节点作为整个链表的开端,每次操作就可以从头节点开始,还需一个属性size,来存储我们链表的大小~

所以开始构造

public class LinkList<dataType> {

    private int size;//链表长度属性

    private Node head = new Node(null);//头节点,数据域是空的,默认指针(下一个对象)也是(指向)空的

}

对于链表我们可以参考java.util包给我们提供的LinkedList的方法来,但是我们必须实现以下基本操作

1、初始化

new 关键字就已经初始化了~此处也不需要什么参数,默认构造函数就行

2、插入操作

方法add(节点的数据)    在链表末尾插入新元素(Node)

public void add(dataType value) {

       Node<dataType> tmp = head;//使用一个临时变量存储head节点

        while (tmp.getNext() != null) {//对临时节点进行移动操作

            tmp = tmp.getNext();

        }//直到移动到末尾,此时tmp为链表最后一个节点(最后一个节点没有指针,指向空,既引用的对象是NULL)

        tmp.setNext(new Node<dataType>(value)); //为最后一个节点设置下一个节点

        this.size++;//链表长度+1

}


方法add(链表位置,节点的数据)   为链表指定位置添加新节点

public void add(int index, dataType value) {

    if (index < 0 || index > this.size) {//判断位置是否合法,既下标是否小于0,或者超出最链表的大小

        throw new ArrayIndexOutOfBoundsException("插入的位置不合法");

    } else {

        int counter = -1;//设置一个counter存储当先节点的下标,因为第一个head不能算进去所以从-1开始计算

        Node tmp = head;//使用后临时节点保存head

        while (tmp != null) {//遍历链表

            if (counter == index - 1) {//指定检查下标是否与当前下标吻合,因为是插入操作,我们必须要找到插入点的前一个节点,吧前一个节点的NEXT指向新节点,然后将新节点的next指向原来插入点新节点的下一个节点。

                Node node = new Node<dataType>(value);//新建节点存储节点的数据

                Node nextNode = tmp.getNext();//使用nextnode表示当前节点的下一个节点,既本来是插入点的下一个节点

                tmp.setNext(node);//当前tmp节点就是插入点前的节点,设置插入点前的节点的下一个节点为我们new 的节点

                node.setNext(nextNode);//为新节点设置下一个节点为下一个节点

                this.size++;//链表长度+1

                break;

            }

            tmp = tmp.getNext();//遍历时的操作

            counter++;//遍历时的操作

        }

    }

}


add(int index,dataType value)

方法addFirst(新节点的值)//在头节点后面插入新节点

public void addFirst(dataType value) {

    Node tmp = head.getNext();//使用临时节点存储原来的第一个节点

    head.setNext(new Node<dataType>(value));//设置新的第一个节点

    head.getNext().setNext(tmp);//新节点的下一个节点为原来的第一个节点

    this.size++;//长度+1

}


方法addLast(新节点的值)//在链表尾部增加新节点和无位置参的add一样

public void addLast(dataType value) {

    Node<dataType> tmp = head;

    while (tmp.getNext() != null) {

        tmp = tmp.getNext();

    }

    tmp.setNext(new Node<dataType>(value));

    this.size++;

}

3、数据查找

方法get(获取数据的位置)

public dataType get(int index) {

    if (index < 0 || index > this.size - 1) {//判断位置是否合法

        throw new ArrayIndexOutOfBoundsException("获取的位置不合法");

    } else {

        Node<dataType> tmp = head;

        int counter = -1;

        while (tmp != null) {//遍历链表

            if (counter == index) {

                return (dataType) tmp.getNodeData();//返回数据域就行了

            }

            tmp = tmp.getNext();

            counter++;

        }

    }

    return null;

}



方法getFirst()获取第一个节点的数据

public dataType getFirst() {

    return (dataType) head.getNext().getNodeData();//只需要返回数据域就行了

}



方法getLast()获取最后一个节点的数据

public dataType getLast() {

    Node tmp = head;

    while (tmp.getNext() != null) {

        tmp = tmp.getNext();

    }

    return (dataType) tmp.getNodeData();

}



4、删除操作

方法clear()清空操作,清空整个链表只需要吧头节点的下一个指向空就行了,后面的节点由于没有被引用就会被java的垃圾回收机制给清理了~java万岁不需要手动回收内存~
public void clear() {

    head.setNext(null);

}


remove(指定位置)删除指定位置的元素

public dataType remove(int index) {

    if (index < 0 || index > this.size - 1) {

        throw new ArrayIndexOutOfBoundsException("删除的位置不合法");

    } else {

        int counter = -1;

        Node tmp = head;

        while (tmp != null) {

            if (counter == index - 1) {

                Node removeNode = tmp.getNext();

                tmp.setNext(tmp.getNext().getNext());//将删除点的next指向下一个的下一个就相当于略过了下一个就行了

                this.size--;//长度-1

                return (dataType) removeNode.getNodeData();//返回删除节点的数据

            }

            counter++;

            tmp = tmp.getNext();

        }

    }

    return null;

}


remove()



5、替换

方法set(替换位置,替换的数据)根据指定位置替换数据,很简单找到相应位置用setNodeData替换数据就行了

public dataType set(int index, dataType value) {

    if (index < 0 || index > this.size - 1) {

        throw new ArrayIndexOutOfBoundsException("修改的位置不合法");

    } else {

        int counter = -1;

        Node tmp = head;

        while (tmp != null) {

            if (counter == index) {

                dataType replacData = (dataType) tmp.getNodeData();

                tmp.setNodeData(value);

                return replacData;

            }

            tmp = tmp.getNext();

            counter++;

        }

    }

    return null;

}



6、拓展(链表转化为数组)

方法toArray()将链表转换数组,很简单,根据链表长度新建数组,然后遍历装进数组就行了

public Object[] toArray() {

    Object[] array = new Object[this.size];

    Node tmp = head;

    int counter = -1;

    while (tmp.getNext() != null) {

        counter++;

        tmp = tmp.getNext();

        array[counter] = tmp.nodeData;

    }

    return array;

}



7、其他操作

获取链表长度

public int size() {

    return this.size;

}


总结

如此我们就完成了整个链表的构造,我们发现在链表的实现中我们大量的用到了遍历,所以在查找数据的实惠相对的链表机会比顺序表慢,因为顺序表可以用下标直接引用,但是在需要大量删除或者添加操作的时候链表的效率明显就会比顺序表快,因为在增加或者删除数据的时候链表只需要改变一下各个节点的引用关系就行了,不需要像顺序表一样移动大量元素。

而且链表也无需考虑容量问题因为增加节点只需要引用就行了,也解决了顺序表的冗余问题,但是单链表依然存在一些问题,这些遗留的问题就留到下次笔记学习~~

本次代码下载地址

链接:https://pan.baidu.com/s/1cSZoWkFwvrCe_Xd6sp7juw 密码:5wp1

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

推荐阅读更多精彩内容

  • 本文是我自己在秋招复习时的读书笔记,整理的知识点,也是为了防止忘记,尊重劳动成果,转载注明出处哦!如果你也喜欢,那...
    波波波先森阅读 2,775评论 0 10
  • 对我而言,简星是一个不可替代的存在,我内心并没有一种强烈的要和他在一起的情感,然而除了他,心里那个位置再也放不...
    于星峣阅读 293评论 0 0
  • 最优分解问题 设n是一个正整数,现在要求将n分解为若干个互不相同的自然数的和,使这些自然数的乘积最大。输入 ...
    Super_邓帅阅读 4,610评论 2 1
  • 想象一下人类技术的发展曲线图,也许你正沿着一个小山坡走着上坡路,可你却不知道马上你就会撞上山崖了。为方便认知,可以...
    青青狐阅读 891评论 0 1
  • 体验产品:UC头条 版本:2.0 一、产品介绍 UC头条是UC浏览器团队潜心打造的新闻资讯推荐平台,拥有海量的新闻...
    kk空空阅读 541评论 0 0