数据结构-链表(非常重要)

链表的概念及结构

链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的。
实际中链表的结构非常多样,虽然有这么多的链表的结构,但是重点掌握两种:

  • 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶,图的邻接表等等。另外这种结构在笔试面试中出现很多。
    在这里插入图片描述
  • 无头双向链表:在Java的集合框架中LinkedList底层实现就是无头双向循环链表。
    在这里插入图片描述

链表的实现

测试文件

public class TestDemo2 {
    public static void main(String[] args) {
        MyLinkedList myLinkedList = new MyLinkedList();
        myLinkedList.addLast(3);
        myLinkedList.addLast(2);
        myLinkedList.addLast(3);
        myLinkedList.addLast(3);
        myLinkedList.addLast(5);
        myLinkedList.addLast(3);
        myLinkedList.addLast(7);
        myLinkedList.display();
        System.out.println(myLinkedList.contains(6));
        System.out.println(myLinkedList.size());
        myLinkedList.addIndex(0,11);
        myLinkedList.display();
        myLinkedList.remove(7);
        myLinkedList.removeAllKey(3);
        myLinkedList.display();
        myLinkedList.display();
        System.out.println("清空之前");
        myLinkedList.clear();
        myLinkedList.display();
    }
}

链表的功能实现文件

/*无头单向非循环链表实现*/
class Node {
    public int data;//默认为0
    public Node next;//默认为null
    public Node(int data){
        this.data = data;
        this.next = null;
    }

}
public class MyLinkedList {
    public Node head;//保存单链表的头节点的引用(地址),默认为null
    public void addFirst(int data){//头插法(用构造方法将传来的数字转换为节点对象,构造方法就是实例化对象的)
        Node node = new Node(data);//这行代码就将传入的data数字创造成了一个节点。
       if (this.head == null){//第一次插入节点
           this.head = node;
           return;
       }
        node.next = this.head;
        this.head = node;
    }
    public void addLast(int data){//尾插法
    Node node = new Node(data);
    if (this.head == null){//第一次尾插入节点
        this.head = node;
        return;
    }
    Node cur = this.head;
    while (cur.next != null){
        cur = cur.next;
    }
    cur.next = node;
    }
    private Node searchIndex(int index){//找到index位置的前一个节点的地址
        if(index < 0||index > this.size()){//判断index的位置是否合法
            throw new RuntimeException("index位置不合法!");
        }
        Node cur = this.head;
        while (index-1!=0) {//往后走index-1步
            cur = cur.next;
            index--;
        }
        return cur;
    }
    public void addIndex(int index,int data){//任意位置插入,第一个数据节点为0号下标
        /*1:首先判断index位置是否为0,为0的话可以按照头插法来做
        * 2:然后定义一个cur走index-1步
        * 3:再去该位置上插入:node.next = cur.next
        *                    cur.next = node;*/
        if (index == 0){
            addFirst(data);//头插法
            return;
        }
         if (index == this.size()){
            addLast(data);//尾插法
            return;
        }
        Node node = new Node(data);
        Node cur = searchIndex(index);
        node.next = cur.next;
        cur.next = node;
    }
    public boolean contains(int key){//查找是否包含关键字key,也就是关键字key是否在单链表中
        Node cur = this.head;
        while (cur != null){
            if (cur.data == key){
                return true;
            }
            cur = cur.next;
        }
        return false;
    }
    private Node searchPrev(int key){//找到要删除节点的头一个节点(称为前驱)
        Node prev = this.head;
        while (prev.next != null){
            if (prev.next.data == key){
                return prev;
            } else {
                prev = prev.next;
            }
        }
        return null;//走到这一步说明没有找到要删除的节点,就返回Null
    }
    public void remove(int key){//删除第一次出现关键字为key的节点
        if (this.head == null){//判断链表中是否有数据,也就是看头节点是否为null
            return;
        }
        if(this.head.data == key){//要删除的节点是头节点的话
                this.head = this.head.next;
                return;
        }
        Node prev = searchPrev(key);//找到要删除元素的前一个节点
        if (prev == null){
            System.out.println("根本没有要删除的节点");
            return;
        }
        Node del = prev.next;
        prev.next = del.next;
    }
    public void removeAllKey(int key){//删除所有值为key的节点
        Node prev = this.head;
        Node cur = this.head.next;//代表要删除的节点
        while (cur != null){
            if (cur.data == key){
                prev.next = cur.next;
                cur = cur.next;
            } else {
                prev = cur;
                cur = cur.next;
            }
        }
        if (this.head.data == key){//如果删除的元素在头节点
            this.head = this.head.next;
        }
    }
    public int size(){//得到单链表的长度
        int count = 0;
        Node cur = this.head;
        while (cur != null){
            count++;
            cur = cur.next;
        }
        return count;
    }
    public void display(){//打印该链表
    Node cur = this.head;
    while (cur != null) {
        System.out.print(cur.data+" ");
        cur = cur.next;
    }
    }
    public void clear(){//清空该链表
        this.head = null;
    }
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值