线性表的链式存储——链表

目录

1.概念

2.链表

2.1 单链表概念及结构

2.2双链表的概念及结构

2.3 循环链表 

3.链表的具体使用

4.自己实现链表及方法:

双链表:

单链表:


1.概念

        链式存储是常用的动态存储方式,相对于顺序表,可以更好的任意插入与删除,而采用链式存储的结构叫做链表。

        链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。      

        从链接方式的角度:链表分为单链表、双链表及循环链表;

        从实现方式的角度:链表分为动态链表和静态链表;

2.链表

2.1 单链表概念及结构

 概念:

        单链表是通过一个一个结点进行连接,而链表并不像顺序表一样存储的是一组地址连续的存储单元,而是非连续的。因此,链表中的结点不仅需要存储自己的数据元素值(数据域),还需要存储下一个结点的地址(指针域)。

 结构:

        

        单链表的每个结点的地址都存储在其前驱结点的指针域中,因此第一个结点无前驱,这个时候我们可以设置一个头指针Head指向第一个结点。而最后一个结点后面没有结点,所以最后一个结点指针域为空(Null)

 单链表结构:

2.2双链表的概念及结构

概念:

        每个结点相对与单链表多了一个指针域,其它与单链表基本相同。

结构:

2.3 循环链表 

概念:

        循环链表是建立在单链表和双链表的基础上,将头尾相连,形成一个环,这就是循环链表,可分为:循环单链表、循环双链表。

 

3.链表的具体使用

方法解释
add(E e)尾插 e

add(int i, E e) 

把e插在i位置
addAll(Collection<? extends E> c)尾插c
addFirst(E e)头插e
remove(int i)删除i坐标元素
remove(int i)删除i坐标元素
get(int i)获得i坐标元素
set(int i , E e)将i坐标元素换为e
clear()清空
contains(object o )判定o是否存在
indexOf(object  o)返回第一个o所在位置的下标
lastIndexOf(object o)返回最后一个o下标
subList(int f, int t)截取f坐标到t坐标list

 代码实现:

public class Test1 {
    public static void main(String[] args) {
        System.out.println(list.add(1));//尾插1,Boolean
        list.addFirst(2);//头插2
        System.out.println(list);
        list.addLast(3);//尾插3
        System.out.println(list);
        list.add(1,4);//1坐标插入4
        System.out.println(list);
        list.remove(2);//删除2坐标元素
        System.out.println(list);
        System.out.println(list.get(2));//获得2坐标元素
        System.out.println(list);
        list.set(1,3);//将1坐标元素改为3
        System.out.println(list);
        System.out.println(list.contains(3));//是否含5
        System.out.println(list.contains(6));//是否含6
        System.out.println(list.indexOf(3));//第一个3的下标
        System.out.println(list.lastIndexOf(3));//最后一个3的下标
        System.out.println(list.subList(0,1));//截取[0,1)的list,前闭后开
        System.out.println(list.isEmpty());//list中是否有元素
        list.clear();//清空
        System.out.println(list.isEmpty());
    }
}

运行结果:

true
[2, 1]
[2, 1, 3]
[2, 4, 1, 3]
[2, 4, 3]
3
[2, 4, 3]
[2, 3, 3]
true
false
1
2
[2]
false
true

4.自己实现链表及方法:

注意:

        上面这些方法的实现,我们可以直接用,但是我们也可以创建自己的链表,实现自己的方法,让我们更好的理解,提升我们的代码能力。

        代码的实现我放在了下面,但是最好自己实现一遍。

双链表:

public class MyLinkedList {
    static class ListNode{
        public int val;
        public ListNode prev;
        public ListNode next;

        public ListNode(int val) {
            this.val = val;
        }
    }
    public ListNode head;
    public ListNode last;
    //头插法
    public void addFirst(int data){
        ListNode listNode = new ListNode(data);
        if (head == null){
            head = listNode;
            last = listNode;
        }else{
            head.prev = listNode;
            listNode.next = head;
            head = listNode;
        }
    }
    //尾插法
    public void addLast(int data){
        ListNode listNode = new ListNode(data);
        if(last == null){
            last = listNode;
            head = listNode;
        }else{
            last.next = listNode;
            listNode.prev = last;
            last = listNode;
        }
    }
    //任意位置插入,第一个数据节点为0号下标
    public void addIndex(int index,int data){
        ListNode listNode = new ListNode(data);
        if(index < 0 || index > size()){
            System.out.println("不合法");
            return;
        }
        if(index == 0){
            addFirst(data);
            return;
        }
        if (index == size()){
            addLast(data);
            return;
        }
        ListNode cur = head;
        for (int i = 0; i < index; i++) {
            cur = cur.next;
        }
        listNode.next = cur;
        cur.prev.next = listNode;
        listNode.prev = cur.prev;
        cur.prev = listNode;
    }
    //查找是否包含关键字key是否在单链表当中
    public boolean contains(int key){
        ListNode cur = head;
        while (cur != null){
            if(cur.val == key){
                return true;
            }
        }
        return false;
    }
    //删除第一次出现关键字为key的节点
    public void remove(int key){
        ListNode cur = head;
        while (cur != null){
            if(cur.val == key){
                if(cur == head){
                    head = head.next;
                }else{
                    if (cur.next == null) {
                        cur.prev.next = null;
                        last = cur.prev;
                    }else{
                        cur.prev.next = cur.next;
                        cur.next.prev = cur.prev;
                    }
                }
                return;
            }else{
                cur = cur.next;
            }
        }
        System.out.println("没有这个节点");
    }
    //删除所有值为key的节点
    public void removeAllKey(int key){
        ListNode cur = head;
        while (cur != null){
            if(cur.val == key){
                if(cur == head){
                    head = head.next;
                }else{
                    if (cur.next == null) {
                        cur.prev.next = null;
                        last = cur.prev;
                    }else{
                        cur.prev.next = cur.next;
                        cur.next.prev = cur.prev;
                    }
                }
            }
            cur = cur.next;
        }
    }
    //得到单链表的长度
    public int size(){
        int count = 0;
        ListNode cur = head;
        while (cur != null){
            count++;
            cur = cur.next;
        }
        return count;
    }
    public void display(){
        ListNode cur = head;
        while (cur != null){
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
        System.out.println();
    }
    public void clear(){
        head = null;
    }
}

单链表:

public class SingleLinkedList {
    class ListNode{
        public int val;
        public ListNode next;
        public ListNode(int val) {
            this.val = val;
        }
    }
    public void createNode(){
        ListNode listNode1 = new ListNode(12);
        ListNode listNode2 = new ListNode(23);
        ListNode listNode3 = new ListNode(34);
        ListNode listNode4 = new ListNode(45);
        ListNode listNode5 = new ListNode(45);
        head = listNode1;
        listNode1.next = listNode2;
        listNode2.next = listNode3;
        listNode3.next = listNode4;
        listNode4.next = listNode5;
    }
    public ListNode head;
    //打印
    public void show(){
        ListNode cur = head;
        for (int i = 0; i < size(); i++) {
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
        System.out.println();
    }
    //长度
    public int size(){
        ListNode cur = head;
        int count = 0;
        while(cur != null){
            cur = cur.next;
            count++;
        }
        return count;
    }
    //查找
    public boolean contains(int key){
        ListNode cur = head;
        if(cur == null){
            return false;
        }
        while (cur.val != key){
            if(cur.next == null){
                return false;
            }
            cur = cur.next;
        }
        return true;
    }
    //头插
    public void addFirst(int data){
        ListNode newNode = new ListNode(data);
        newNode.next = head;
        head = newNode;
    }
    //尾插
    public void addLast(int data){
        ListNode newNode = new ListNode(data);
        ListNode cur = head;
        while (cur.next != null){
            cur = cur.next;
        }
        cur.next = newNode;
    }
    //随意插
    public void addIndex(int index,int data){
        ListNode cur = head;
        ListNode newNode = new ListNode(data);
        if(index == 0){
            addFirst(data);
            return;
        }
        if(index < 0 || index > size() || cur == null){
            throw new IndexOutOfBounds("数组不合法,越界: " + index);
        }
        if(index == size()){
            addLast(data);
            return;
        }
        for (int i = 1; i < index; i++) {
            cur = cur.next;
        }
        newNode.next = cur.next;
        cur.next = newNode;
    }
    //删除第一次出现关键字为key的节点
    public void remove(int key){
        ListNode cur = head;
        ListNode pver = head;
        if(cur == null){
            System.out.println("链表无节点");
            return;
        }
        if(cur.val == key){
            head = head.next;
        }
        while(cur.val != key){
            if(cur.next == null){
                System.out.println("无此节点");
                return;
            }
            pver = cur;
            cur = cur.next;
        }
        if(cur.val == key){
            pver.next = cur.next;
            return;
        }
    }
    //删除所有值为key的节点
    public void removeAllKey(int key){
        if(head == null) {
            return;
        }
        ListNode cur = head.next;
        ListNode prev = head;
        while (cur != null) {
            if(cur.val == key) {
                prev.next = cur.next;
                cur = cur.next;
            }else {
                prev = cur;
                cur = cur.next;
            }
        }
        if(head.val ==  key) {
            head = head.next;
        }
    }
    //清除所有数据
    public void clear(){
        head = null;
    }
}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是小辰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值