Связанный список структур данных Java, общие операции и анализ кода

1. Принцип
вставьте сюда описание изображения
элемента (элемента) связанного списка: содержимое, которое фактически существует в
узле (узле) линейной переменной: структура, введенная для организации связанного списка, помимо сохранения наших элементов, также сохранит ссылку на следующий узел

public class Node {
    
    
    public int val;   //结点内存储的内容
    public  Node next;//保存指向下一个结点的引用,其中尾结点的next=null

    public Node(int val){
    
    
        this.val=val;
    }
}

2. Создайте версию связанного списка
без марионеточных узлов

    public static Node createList(){
    
    
        Node a=new Node(1);
        Node b=new Node(2);
        Node c=new Node(3);
        Node d=new Node(4);
        a.next=b;
        b.next=c;
        c.next=d;
        d.next=null;
        return a;
    }

версия с марионеточным узлом

public static Node creatListWithDummy(){
    
    
    Node dummy=new Node(0);
    Node a=new Node(1);
    Node b=new Node(2);
    Node c=new Node(3);
    Node d=new Node(4);
    dummy.next=a;//在原本链表基础上,在头结点的前边创建一个前驱节点
    a.next=b;
    b.next=c;
    c.next=d;
    d.next=null;
    return dummy;
}

3. Соответствующий код операции и анализ
1. Обход связанного списка

    public static void print(Node head)
    {
    
    
        for(Node cur=head;cur!=null;cur=cur.next)
        {
    
    
            System.out.println(cur.val);
        }
    }

Передайте головной узел в функцию, назначьте головной узел новому узлу nur и судите каждый раз по циклу. Если cur пуст, цикл заканчивается. Если он не пуст, он будет указывать на следующий узел. Согласно характеристикам связанного списка, в последнем узле следующий узел равен нулю, поскольку следующего узла нет. Распечатайте каждый цикл и, наконец, реализуйте обход связанного списка.
2. Узел хвостовой вилки

    public static Node insertTail(Node head,int val)
    {
    
    
        Node newNode=new Node(val);//创建一个新结点,初始化为传入的参数值
        if(head==null)
        {
    
    
            return newNode;//如果头结点为空,则说明这是一个空链表,则新结点就为这个链表的头结点
        }
       //1.先找到末尾节点
       Node prev =head;
        while(prev.next!=null){
    
    
            prev=prev.next;//经过遍历,找到链表的尾部结点 
        }
        //循环结束,prev就是最后一个节点了
         newNode.next= null;
        prev.next=newNode;
        return head;
    }

вставьте сюда описание изображенияБлок-схема реализации кода хвостовой заглушки
вставьте сюда описание изображенияЛогическая схема хвостовой заглушки

3. Удалить узлы по значению

   //删除节点,此时按照值来删除
    public  static  Node remove(Node head,int value)
    {
    
    
        if(head==null){
    
    
            return null;
        }
        if(head.val==value)
        {
    
    
            //要删除的节点就是头节点
            head=head.next;
            return head;
        }
        //1.先找到val这个值对应的值
        //同时也要找到val的前一个位置
        Node prev=head;
        while (prev!=null&&prev.next!=null&&prev.next.val!=value)
        {
    
    
            prev=prev.next;
        }
        //循环结束之后,prev就指向待删除节点的前一个节点了
        if(prev==null||prev.next==null)
        {
    
    
            //没有找到值为val的节点
            return head;
        }
        //2.真正进行删除了,toDelete指向要被删除的节点
        Node toDelete=prev.next;
        prev.next=toDelete.next;
        return head;
    }

вставьте сюда описание изображения
4. Удалить по местоположению (1)

        //删除节点,按照位置来删除
    public static Node remove(Node head,Node toDelete)
    {
    
    
        if(head==null)
        {
    
    
            return null;
        }
        if(head==toDelete)
        {
    
    
            //要删除的就是头节点
            head=head.next;
            return head;
        }
        //1.先需要找到toDelete的的前一个节点
        Node prev=head;
        while(prev!=null&&prev.next!=toDelete)
        {
    
    
            prev=prev.next;
        }
        if(prev==null)
        {
    
    
            //没找到
            return head;
        }
        //2.进行删除
        prev.next=toDelete.next;
        return head;
    }

вставьте сюда описание изображения
По сравнению с удалением по значению, единственная разница в этой идее программирования состоит в том, что условия оценки в процессе обхода для поиска узлов различны.При поиске по местоположению вам необходимо сравнить, равен ли предыдущий.следующий удаляемому узлу, потому что цель состоит в том, чтобы найти предыдущий узел узла, который нужно удалить.

5. Удалить по местоположению (2)

    public static Node remove2(Node head,Node toDelete)
    {
    
    
        if(head==null){
    
    
            return null;
        }//如果链表为空,直接返回null
        if(head==toDelete){
    
    
            head=head.next;
            return head;
        }//如果头节点为要删除的节点,让头节点的后继节点成为新的头节点,实现删除
        Node nextNode=toDelete.next;
        toDelete.val=nextNode.val;
        toDelete.next=nextNode.next;
        return head;
    }

Этот метод,

6. Рассчитайте функцию длины связанного списка

    public static int size(Node head)
    {
    
    
        int size=0;
        for (Node cur=head;cur!=null;cur=cur.next)
        {
    
    
            size++;
        }
        return size;
    }

Через головной узел пройдите по связанному списку и используйте целочисленный размер в качестве счетчика.

7. Удалить узлы в соответствии с индексами узла

 //给定节点下标来删除
    public static Node remove3(Node head,int index){
    
    
        if(index<0||index>+size(head))
        {
    
    
            return head;
        }
        //如果index等于0,意味着要删除头节点
        if(index==0){
    
    
            head=head.next;
            return head;

        }
        //1.还是要先找到待删除节点的前一个位置.index-1这个节点就是前一个位置
        Node prev=head;
        for(int i=0;i<index-1;i++)
        {
    
    
            prev=prev.next;
        }
        //循环结束之后,prev就指向了待删除节点的前一个位置
        //2.真正进行删除
        Node toDelete=prev.next;
        prev.next=toDelete.next;
        return head;
    }

вставьте сюда описание изображения
Ключом к удалению в соответствии с нижним индексом узла является то, что условие решения цикла состоит в том, чтобы prev указывал на предыдущий узел удаляемого узла, а последующие операции были такими же, как и у предыдущих функций.
8. Удалить элементы из связанного списка с марионеточными узлами

//针对带傀儡节点的链表,删除指定元素
    public static void removeWithDummy(Node head,int val)
    {
    
    
        //此时不必考虑到head引用修改的问题,也不必单独考虑删除第一个节点的事情了
        Node prev=head;
        while (prev!=null&&prev.next!=null&&prev.next.val!=val)
        {
    
    
            prev=prev.next;
        }
        //当这个循环结束的时候,要么是prev到达了链表末尾,要么是找到了val匹配的值
        if(prev==null||prev.next==null)
        {
    
    
            //没有找到对应的点
            return;
        }
        //找到了对应的点
        //如果要删除val正好是第一个节点,此时prev正好是指向head的
        Node toDelete=prev.next;
        prev.next=toDelete.next;
        return;
    }

9. Узлы без связанного списка марионеток удаляются хвостом

    //针对不带傀儡节点的链表,进行尾删操作
    public static Node removeTail(Node head)
    {
    
    
        if(head==null){
    
    
            return null;
        }
        if(head.next==null)
        {
    
    
            //链表里只有一个节点,尾删的节点就是这个head本身
            //此时删除该节点之后,这个链表就变成空链表了
            return null;
        }
//一般的情况,需要找到尾部节点的前一个节点
        Node prev=head;
        Node toDelete=prev.next;
        while(prev!=null&&prev.next!=null)
        {
    
    
            toDelete=prev.next;
            if(toDelete.next==null)
            {
    
    
                break;
            }
            prev=prev.next;
        }
        //接下来删除这个节点即可
        //由于toDelete已经是最后一个节点了,他的next一定是null
        prev.next=null;
        return head;
    }

вставьте сюда описание изображения
10. Замените массив связным списком

public static Node arrayToLinkedList(int[] array)
    {
    
    
        //遍历数组,把元素进行尾插即可
        //每次尾插,都需要知道当前链表的末尾节点
        //每次重新找这个末尾节点,太麻烦了
        //可以直接用一个引用把尾节点记住

        //head就是头节点的引用,初始情况下,链表是空的
        Node head=null;
        //tail也是空的
        Node tail=null;
        for(int x:array)
        {
    
    
            Node node=new Node(x);
            //把node进行尾插
            //需要判定当前链表是否为空
            if(head==null)
            {
    
    
                head=node;
                tail=node;
            }else
            {
    
    
                //链表不为空的时候。再进行新的插入,就不必管head了,直接操作tail即可
                tail.next=node;
                //一旦插入完成,新节点就成了tail,需要更新tail的指向
                tail=tail.next;
            }

        }
        return head;
    }

Acho que você gosta

Origin blog.csdn.net/qq_45742383/article/details/114703400
Recomendado
Clasificación