Learning of Java singly linked list

I have learned about linear structures before: sparse arrays and queues. Today, I will learn linear structures-linked lists.

1. Common forms of
linked lists : linked lists are ordered lists. Generally, linked lists include singly linked lists, doubly linked lists, and circular linked lists.
2. What is a singly-linked list? A
singly-linked list is a chained access data structure that uses a set of storage units with arbitrary addresses to store the data elements in the linear table. The data in the linked list is represented by nodes. The composition of each node: element (the image of the data element) + pointer (indicating the storage location of the subsequent element), the element is the storage unit for storing the data, and the pointer is connected to each The address data of the node. ( Baidu Encyclopedia explanation )
3. Through specific diagrams to understand what is a singly linked list.

Illustration: Insert picture description here
Summarize the characteristics of the linked list through the above figure:

  1. The linked list is stored in the form of nodes, which is a chain storage.
  2. Each node contains a data field, a next field, and points to the next node.
  3. The nodes of the linked list are not necessarily stored continuously.
  4. The linked list is divided into a linked list with a head node and a linked list without a head node, which are determined according to actual needs.

Schematic diagram of the logical structure of the linked list: (single linked list with the head node)

Insert picture description here
Through the above concepts and diagrams, everyone must have a preliminary understanding of singly linked lists.
Let's learn more about the operation of adding, deleting, modifying and checking singly linked lists by simulating singly linked lists.

Simulate singly linked list usage scenarios:

  • Use a one-way linked list with head to achieve-Water Margin Hero Ranking Management
  1. Complete the operation of adding, deleting, modifying and checking heroes.
  2. When adding heroes in the first method, add them directly to the end of the linked list.
  3. In the second method, when adding a hero, the hero is inserted into the designated position according to the ranking award (if there is this ranking, the addition fails and a prompt is given).

As mentioned earlier, a node is composed of the data field and the next field, where the data field stores the hero rank, name, nickname, and the next field stores the address of the next node.

Object-oriented thinking: each node is regarded as an object to encapsulate data domain information and next domain information.

The specific code is as follows:

//定义HeroNode 每个HeroNode对象就是一个节点
class HeroNode {
    
    
	//英雄排名
    public int no;
    //英雄姓名
    public String name;
    //英雄绰号
    public String nickname;
    //指向下一个节点
    public HeroNode next;

    //初始化数据
    public HeroNode(int no, String name, String nickname) {
    
    
        this.no = no;
        this.name = name;
        this.nickname = nickname;
    }

    //展示英雄 重写toString方法
    @Override
    public String toString() {
    
    
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickname='" + nickname + '\'' +
                '}';
    }
}

Then analyze the operations of adding, deleting, modifying, and checking singly linked lists one by one.

01 Adding a singly linked list

The operation of adding a singly linked list can be divided into two ways: directly adding to the end of the linked list (without sorting), and inserting the hero into the specified position according to the ranking.

Method 1: Directly add to the end of the linked list.
Analysis of the idea:
1. Create a head node first (the position of the head node remains unchanged, to ensure that each new node can be added to the end of the linked list), which is used to represent the head of the singly linked list
2. Every time a node is added to the end of the singly linked list
3. With the help of auxiliary variables, it helps to traverse the entire linked list
3. Traverse:
Find the location of the
new node temp.next points to the new node

Specific code:

    //添加节点
    public void add(HeroNode heroNode) {
    
    
        //定义辅助变量指向头节点
        HeroNode temp = head;
        //找到当前链表的最后节点 需要遍历
        while (true) {
    
    
            //判断是否存在下一个节点
            if (temp.next == null) {
    
    
                break;
            }
            //如果没有找到temp后移
            temp = temp.next;
        }
        //将最后这个节点的next 指向新节点
        temp.next = heroNode;
    }

Method 2: Insert the hero into the specified position according to the ranking.
Analysis of the idea:
1. The position to find the added node should be between the auxiliary variable and the auxiliary variable .next
2. After the position is found
3.temp.next = heroNode;
4.heroNode. next = temp.next;
5. The temp we found is the previous node at the added position

Specific code:

public void addByOrder(HeroNode heroNode) {
    
    
      	//定义辅助变量指向头节点
        HeroNode temp = head;
        boolean flag = false;//定义标记 表示是否重复添加英雄
        while (true) {
    
    
        	//如果单链表没有一个节点 结束循环
            if (temp.next == null) {
    
    
                break;
            }
            //单链表节点的序号大于新节点的序号 结束循环
            if (temp.next.no > heroNode.no) {
    
    
                break;
            } else if (temp.next.no == heroNode.no) {
    
    //重复添加英雄
                //将标记符置位true
                flag = true;
                break;
            }
            //后移
            temp = temp.next;
        }
        //添加重复英雄,给与提示
        if (flag) {
    
    
            System.out.printf("准备添加%d号的英雄,已存在不能加入\n", heroNode.no);
        }
        //插入链表 temp的后面
        heroNode.next = temp.next;
        temp.next = heroNode;
    }
02Single Linked List Delete Operation

Thinking analysis:

1. Find the location where the
node needs to be deleted 2. After deleting the node, you need to connect the previous node of the deleted node with the next node
3. temp.next == temp.next.next;

Specific code:

 public void delete(int no) {
    
    
        //辅助变量
        HeroNode temp = head;
        boolean flag = false;
        //循环遍历找出需要删除的节点位置
        while (true) {
    
    
            if (temp.next == null) {
    
    
                break;
            }
            if (temp.next.no == no) {
    
    
                flag = true;
                break;
            }
            //后移继续查找要删除节点的位置
            temp = temp.next;
        }
        if (flag) {
    
    
            temp.next = temp.next.next;
        } else {
    
    
            System.out.printf("要删除的节点%d号,不存在", no);
        }
    }
03Single linked list modification operation

Thinking analysis:

1. Find the previous node of the data to be modified
2. You can only modify the name and nickname of the node, and cannot modify the number of the node. If you want to modify it to add a node

Specific code:

 public void update(HeroNode newHeroNode) {
    
    
        //判断是否为空
        if (head.next == null) {
    
    
            System.out.println("链表为空");
            return;
        }
        //辅助变量
        HeroNode temp = head.next;
        boolean flag = false;//标记是找到修改的节点
        //循环判断是否存在要修改的节点信息
        while (true) {
    
    
            if (temp == null) {
    
    
                break;
            }
            if (temp.no == newHeroNode.no) {
    
    
                flag = true;
                break;
            }
            //如果上述条件都不满足,则继续循环遍历查找要修改的节点
            temp = temp.next;
        }
        //判断标记是否为true
        if (flag) {
    
    
            temp.name = newHeroNode.name;
            temp.nickname = newHeroNode.nickname;
        } else {
    
    
            System.out.printf("要修改的节点%d号,不存在\n", newHeroNode.no);
        }
    }
04 singly linked list lookup operation

Thinking analysis:

  1. Determine whether the linked list is empty
  2. Output node information directly (override the toString method)
//显示链表[遍历]
    public void list() {
    
    
        //判断链表是否为空
        if (head.next == null) {
    
    
            System.out.println("链表为空");
            return;
        }
        //因为头节点不能动,需要一个辅助变量来遍历
        HeroNode temp = head.next;
        while (true) {
    
    
            //判断是否到链表最后
            if (temp == null) {
    
    
                break;
            }
            //输出节点信息
            System.out.println(temp);
            //循环完第一个节点后应该 指向下一个节点
            temp = temp.next;
        }
    }
05Integration

First define a SingleLinkList class, and then define the head node. Add the above-mentioned addition, deletion, modification and investigation method. Just test it.

//定义SingleLinkedList
class SingleLinkedList {
    
    
    //定义头结点 位置保持不变
    private HeroNode head = new HeroNode(0, "", "");

    /**
     * 1.找到当前链表的最后节点
     * 2.将这个节点的next 指向下一个节点
     *
     * @param heroNode
     */
    //添加节点
    public void add(HeroNode heroNode) {
    
    
        //定义辅助变量指向头节点
        HeroNode temp = head;
        //找到当前链表的最后节点 需要遍历
        while (true) {
    
    
            //判断是否存在下一个节点
            if (temp.next == null) {
    
    
                break;
            }
            //如果没有找到temp后移
            temp = temp.next;
        }
        //将最后这个节点的next 指向新节点
        temp.next = heroNode;
    }

    public void addByOrder(HeroNode heroNode) {
    
    
        //找到添加节点的位置  应该是在 辅助变量和辅助变量.next 中间
        //找到了位置以后
        //temp.next = heroNode;
        //heroNode.next = temp.next;
        //我们找到的temp,是位于添加位置的前一个节点
        HeroNode temp = head;
        boolean flag = false;//定义标记 表示是否重复添加英雄
        while (true) {
    
    
            if (temp.next == null) {
    
    
                break;
            }
            if (temp.next.no > heroNode.no) {
    
    
                break;
            } else if (temp.next.no == heroNode.no) {
    
    //重复添加英雄
                //将标记符置位true
                flag = true;
                break;
            }
            //后移
            temp = temp.next;
        }
        if (flag) {
    
    
            System.out.printf("准备添加%d号的英雄,已存在不能加入\n", heroNode.no);
        }
        //插入链表 temp的后面
        heroNode.next = temp.next;
        temp.next = heroNode;
    }

    /**
     * 修改单链表的数据信息
     * 1.找到要修改的数据的前一个节点
     * 2.只能修改节点的姓名和昵称 不能修改节点的编号如果要修改成了添加一个节点
     */
    public void update(HeroNode newHeroNode) {
    
    
        //判断是否为空
        if (head.next == null) {
    
    
            System.out.println("链表为空");
            return;
        }
        //辅助变量
        HeroNode temp = head.next;
        boolean flag = false;//标记是找到修改的节点
        //循环判断是否存在要修改的节点信息
        while (true) {
    
    
            if (temp == null) {
    
    
                break;
            }
            if (temp.no == newHeroNode.no) {
    
    
                flag = true;
                break;
            }
            //如果上述条件都不满足,则继续循环遍历查找要修改的节点
            temp = temp.next;
        }
        //判断标记是否为true
        if (flag) {
    
    
            temp.name = newHeroNode.name;
            temp.nickname = newHeroNode.nickname;
        } else {
    
    
            System.out.printf("要修改的节点%d号,不存在\n", newHeroNode.no);
        }
    }

    /**
     * 删除节点信息
     * 思路:
     * 1.找到需要删除节点的位置
     * 2.删除节点后需要将删除节点的前一个节点与后一个节点连接起来
     * temp.next == temp.next.next;
     */
    public void delete(int no) {
    
    
        //辅助变量
        HeroNode temp = head;
        boolean flag = false;
        //循环遍历找出需要删除的节点位置
        while (true) {
    
    
            if (temp.next == null) {
    
    
                break;
            }
            if (temp.next.no == no) {
    
    
                flag = true;
                break;
            }
            //后移继续查找要删除节点的位置
            temp = temp.next;
        }
        if (flag) {
    
    
            temp.next = temp.next.next;
        } else {
    
    
            System.out.printf("要删除的节点%d号,不存在", no);
        }
    }


    //显示链表[遍历]
    public void list() {
    
    
        //判断链表是否为空
        if (head.next == null) {
    
    
            System.out.println("链表为空");
            return;
        }
        //因为头节点不能动,需要一个辅助变量来遍历
        HeroNode temp = head.next;
        while (true) {
    
    
            //判断是否到链表最后
            if (temp == null) {
    
    
                break;
            }
            //输出节点信息
            System.out.println(temp);
            //循环完第一个节点后应该 指向下一个节点
            temp = temp.next;

        }
    }
}
05Summary
  1. With the help of markers, the logic and clarity of the code are realized.
  2. Use auxiliary variables to resolve the embarrassment that the head node cannot move.
  3. Flexible use of object-oriented thinking.
  4. Diagrams may be another way to understand programs.

Guess you like

Origin blog.csdn.net/lirui1212/article/details/111273467