chain structure

Chained storage structure: logically continuous; physically not necessarily continuous; for example, the teacher rolls names to determine the number of people; No. 2 students are behind No. 1; but they do not need to sit in order

linked list

Defect 1 of the previous sequence table
: When I need to put 101 elements; expanding the capacity to 150 will not waste 49 spaces.
2: Every time I delete and insert, I have to move a lot of elements. So it is not suitable for frequent insertion and deletion scenarios; search is more suitable; O(1) can be achieved through subscripts

Linked list: use it as you go; insertion and deletion do not need to move elements. Linked lists have eight structures.
insert image description here
Singly linked list:

Leading node: The data of the first node is meaningless and always marks the head of the linked list. The head plug is also inserted in the back of this.

No head node: the new head node will be changed once the head is inserted
insert image description here
Loop:
one-way cycle without head: the last null becomes the address of the head node; the head will change when the head is inserted; the value of the head is valid

One-way loop leading: the last null becomes the address pointing to the head node;
insert image description here

Implement a one-way linked list without a head

Structural analysis: If we use a class to represent a linked list; then it is very suitable for the nodes inside to be represented by an internal class. :
First, a class represents a linked list; then an inner class (with val; next; provides an initialization constructor; we can specify a value to add nodes); outside is a head pointer.

class MyLink{
    
    

    class Node{
    
    
        public int val;
        //节点类型正好用来存放下一个节点;现在是对象代表节点
        public Node next;
        public Node(int val) {
    
    
            this.val = val;
        }
    }

    Node head=null;




}

1: Provide an initialization method; once called; immediately create 5 nodes for you

  //初始化方法;我在想我们在main方法怎么初始化呢;死去的回忆在攻击我;内部类的实例化
    public void createList(){
    
    
        Node node1=new Node(25);
        Node node2=new Node(250);
        Node node3=new Node(2500);
        Node node4=new Node(25000);
        Node node5=new Node(250000);
     //还需要绑定节点
        node1.next=node2;
        node2.next=node3;
        node3.next=node4;
        node4.next=node5;
        head=node1;

    }

2: The method of printing

  public void print(){
    
    
        Node cur=head;
//        使用cur是因为头指针可不能走
  //  打印链表; 这里遍历是注意是使用cur.next==null还是cur==null
//想想如果是cur.next;那么最后一个val就打印不了;循环进不去。还有问题就是空的时候没有cur.next
     while (cur!=null){
    
    


         System.out.println(cur.val);
           cur=cur.next;
     }


    }

3: Get the length of the linked list method


//    获取链表长度;
public int Size(){
    
    
    Node cur=head;
    int count=0;
    while (cur!=null){
    
    


          count++;
        cur=cur.next;
    }
return count;

}

4: Find whether the keyword k is included

    //    获取链表长度;
    public boolean contains(int key){
    
    
        Node cur=head;

        while (cur!=null){
    
    

        if(cur.val==key){
    
    
//    如果是引用类型就不能用==;字符串得用equles方法。
            return true;
        }

            cur=cur.next;
        }
    return false;

    }

5: Head insertion and tail insertion
method Drawing analysis:
insert image description here
The second solution: it is also applicable when an empty linked list is encountered. Because head is null. The first type of head.next is a null pointer exception.
Tips: When inserting data into the linked list; you must first bind the following nodes. Then bind the previous node.


//    头插法;我们无头;所以头插是直接放到头去;
//    头插需要注意什么细节。如果没有元素?
//    public void head(Node N){
    
    
//直接传节点有点不友好;可以选择传个数进来;你要头插这个数;我们在里面给创建成节点然后插入就好了
        public void addFirst(int data){
    
    
        Node N=new Node(data); 
        if(Size()==0){
    
    
            head=N;
            head.next=null;
            return;
        }
        N.next=head;
        head=N;

    }
//    尾插法
//    需要注意什么细节;如果没有元素;怎么找到最后个元素呢
    public void addLast(int data) {
    
    
     Node N=new Node(data); 
        Node cur=head;
// 让cur去往下遍历; 直到这个就是我们要找的最后个元素
       
        if(Size()==0){
    
    //或者这里写head==null;cur==null更高效。
            head=N;
            head.next=null;
            return;
        }
//找位置;尾插找到位置只需要把原先最后节点的next改成N的节点就好了;N的next本来就是null的
//怎么找;按之前的遍历方法行不行呢;不行的;因为这样子走过了;走到最后一个节点;再进行这一次的循环执行cur=cur.next;cur就变成空了。
//所以我们得让它在倒数的上一次循环执行就应该出来了;经过执行cur=cur.next;就恰好是我们想要的最后位置。所以这里得用cur.next!=null;
    //while(cur!=null){
    
    
  //       cur=cur.next;
//}
        while(cur.next!=null){
    
    
        cur=cur.next;
        }
        N.next=null;
       cur.next=N;



    }

6: Insert to the middle position


//插入到中间节点;以第一个节点为0下标;插入在index下标
//  有什么细节呢;如果是没有元素;如果是只有一个元素;头插尾插
//  index如果是负数呢。如果是0和链表长度那就调用上述的头插和尾插方法。然后就找位置;找到再进行普通的插入
//    还有不能隔着插入;比如只有5个元素;你要插入到10位置
    public void add(int index,int data){
    
    
        Node N=new Node(data);
       if(index<0||index>Size()){
    
    
           System.out.println("位置不合法");
           return;
       }
//       data等于0就包括没有元素的插入;data==Size()尾插的情况
       if(index==0){
    
    
           addFirst(data);

       }
       if(index==Size()){
    
    
           addLast(data);

        }
       //走到这里就是真正的中间插入;先找位置。使用index计数找位置;之前找尾节点也能用这种方法
       //或者倒着走更好;不用创建count变量;走index-1步就找到cur。
        //    条件(index-1 !=0)  cur=cur.next; index--;
        int count=0;
       Node cur=head;
        while (count<index){
    
    

            cur=cur.next;
            count++;
        }
//        cur找到位置;注意先绑定后面节点;画图就能很好看出;哪个地方要改成哪里的值
        N.next=cur.next;
        cur.next=N;


    }

7: The method of deleting val

//    删除值为key的元素;是删除出现的第一个吗 是的
//    删除有什么细节呢;空的时候没法删除;如果删除的是头节点(head往后移即可);尾节点。只有一个元素的情况是属于删除尾节点。
    public Node remove(int key){
    
    
        if(Size()==0){
    
    
            System.out.println("没元素可以删除");
            return null;

        }
          // 删除头节点
        if(head.val==key){
    
    
            head=head.next;


        }
//        删除尾节点;那也得找尾节点;
//        删除只是跳过一个节点;假设cur是删除的前一个节点;
//        让cur.next=cur.next.next.当是尾节点cur.next.next就是null;这种情况也是符合普通情况
         Node cur=  selectago(key);
         if(cur==null){
    
    
             System.out.println("没有这个元素");
             return null;

         }
        //以删除节点为基准;前面一个节点的next等于;下一个节点的地址;因为下一个节点的地址就是这个删除节点的next。
        cur.next=cur.next.next;
         return cur;


    }

    private Node selectago(int key) {
    
    
//        找删除的前一个节点
        Node cur=head;
        while (cur!=null){
    
    

             if(cur.val==key){
    
    

                 return cur;
             }

            cur=cur.next;
        }
        return null;
    }

8: Delete all keys

//删除所有的key;想法是什么;注意细节:首先空是不能删;头不能先删;避免删了后面还是要删头
  public  void removeAllkey(int key){
    
    
//    方法1;循环遍历调用刚才的删除方法;但是;时间复杂度太大了。可达到O(n^2)
//        删除头节点和没有元素情况下还是少不了的;
        if(Size()==0){
    
    
            System.out.println("没元素可以删除");

        }
//先不考虑头的情况;先删除后面的;因为你比如删除5;第一个是;删完第一个万一第二个还是5呢
//删除得要特别注意;要找到前驱才能删除这个节点;cur从头开始;cur等于head.next就不好搞了;还需要记录一下前驱是什么。
          Node cur=head;
        while (cur.next!=null){
    
    
            if(cur.next.val==key) {
    
    
                cur.next = cur.next.next;
            }
            else {
    
    
                cur=cur.next;
            }
        }





//        最后后面删完再看看头是否要删
        if(head.val==key){
    
    
            head=head.next;

        }

    }

9: Clear method

//    清空链表的方法
    public void clean(){
    
    

        head=null;
//   标记删除;插入就覆盖进去;并不是到回收内存的那步;
    }

Guess you like

Origin blog.csdn.net/m0_64254651/article/details/130174108