数据结构--单链表

一、链表是有序的列表,但是它在内存中是存储如下:

 

1) 链表是以节点的方式来存储,是链式存储

2) 每个节点包含 data 域, next 域:指向下一个节点.

3) 如图:发现链表的各个节点不一定是连续存储.

4) 链表分带头节点的链表和没有头节点的链表,根据实际的需求来确定

5) 各个节点是分散的存在,他们的联系是指向,节点A指向了节点B,构建时关键是搭建出联系指向,遍历时只要找到

6) 由后给前赋值,如删除:tempNode.nextNode = tempNode.nextNode.nextNode;

二、单链表(带头结点) 逻辑结构示意图如下

 

三、单链表的应用实例

使用带 head 头的单向链表实现 –水浒英雄排行榜管理完成对英雄人物的增删改查操作

3.1、第一种方法在添加英雄时,直接添加到链表的尾部

3.2、第二种方式在添加英雄时,根据排名将英雄插入到指定位置

1)思路的分析示意图

3.3、修改节点功能

思路

(1) 先找到该节点,通过遍历,

(2)temp.name = newHeroNode.name ; temp.nickname= newHeroNode.nickname

3.4、删除节点

1)思路的分析示意图

四、上代码

Node节点类

 1 public class HeroNode {
 2     public Integer no;
 3     public String name;
 4     public String nickName;
 5     public HeroNode nextNode;
 6 
 7     public HeroNode() {
 8     }
 9 
10     public HeroNode(Integer no, String name, String nickName) {
11         this.no = no;
12         this.name = name;
13         this.nickName = nickName;
14     }
15 
16     @Override
17     public String toString() {
18         return "HeroNode{" +
19                 "no=" + no +
20                 ", name='" + name + '\'' +
21                 ", nickName='" + nickName + '\'' +
22                 '}';
23     }
24 }

服务类

public class SingleLinkListServe {

    //初始化一个头节点,头节点不要动,不存放任何数据
    HeroNode headNode = new HeroNode();

    //1、向链表尾部添加节点
    /**
     * 思路:当不考虑编号的顺序时
     * 1、找到当前链表的最后节点
     * 2、将最后节点的nextNode指向新的节点
     */
    public void addNode(HeroNode newNode){
        //创建一个临时节点
        HeroNode tempNode = headNode;
        //循环,直到找到最后一个节点就退出
        while (true){
            if(tempNode.nextNode == null){
                break;
            }
            tempNode = tempNode.nextNode;
        }
        //循环退出后即找到最后一个节点了,在最后一个节点的nextNode进行添加新节点
        tempNode.nextNode = newNode;
    }

    //2、根据序号添加节点
    /**
     * 思路:(如果有这个排名,则添加失败,并给出提示)
     * 1、找到添加的位置
     * 2、新的节点.nextNode = temp.nextNode
     * 3、temp.next = 新的节点
     */
    public void addByOrder(HeroNode newHeroNode){
        //创建临时节点
        HeroNode tempNode = headNode;
        //创建一个标记
        boolean flag = false;

        while(true){
            if(tempNode.nextNode == null){
                break;
            }
            if(tempNode.nextNode.no > newHeroNode.no){
                break;
            }
            if(tempNode.nextNode.no == newHeroNode.no){
                flag = true;
                break;
            }
            tempNode = tempNode.nextNode;
        }

        if(flag){//编号存在,不能添加
            System.out.printf("编号%d的节点已经存在,不能添加",tempNode.no);
        }else {
            newHeroNode.nextNode = tempNode.nextNode;
            tempNode.nextNode = newHeroNode;
        }


    }
    
     //3、根据编号修改节点信息
    public void update(HeroNode newNode){
        HeroNode tempNode = headNode;
        //是否找到的标识
        boolean flag = false;
        if(headNode.nextNode == null){
            System.out.println("链表为空");
            return;
        }
        while (true){
            tempNode = tempNode.nextNode;
            //最后一个节点
            if(tempNode == null){
                break;
            }
            //找到了,标识为true
            if(tempNode.no == newNode.no){
                flag = true;
                break;
            }
        }
        //根据flag判断是否找到节点
        if(flag){
            tempNode.name = newNode.name;
            tempNode.nickName = newNode.nickName;
        }else {
            System.out.println("未找到节点");
        }
    }
    //4、删除节点
    public void delNode(int no){
        HeroNode tempNode = headNode;
        boolean flag = false;
        if(tempNode == null){
            System.out.println("链表为空");
        }
        while(true){
            if(tempNode.nextNode == null){
                break;
            }
            if(tempNode.nextNode.no == no){
                flag = true;
                break;
            }
            tempNode = tempNode.nextNode;
        }

        if(flag){//表示找到节点了
            tempNode.nextNode = tempNode.nextNode.nextNode;
        }else {
            System.out.println("节点没找到");
        }


    }
    //5、遍历链表
    public void printList(){
        //创建一个临时节点
        HeroNode tempNode = headNode;
        //判断链表是否为空
        if(tempNode.nextNode== null){
            System.out.println("链表为空");
            return;
        }
        while(true){
            //判断是否为最后节点
            if(tempNode.nextNode== null){
                break;
            }
            //非最后节点就输出打印,并将临时节点往下移动
            System.out.println(tempNode.nextNode);
            tempNode = tempNode.nextNode;
        }


    }


}

测试执行类

 1 public class SingleLinkListDemo {
 2     public static void main(String[] args) {
 3         HeroNode heroNode1 = new HeroNode(1,"宋江","及时雨");
 4         HeroNode heroNode2 = new HeroNode(2,"卢俊义","玉麒麟");
 5         HeroNode heroNode3 = new HeroNode(3,"吴用","智多星");
 6         HeroNode heroNode4 = new HeroNode(4,"林冲","豹子头");
 7 
 8         SingleLinkListServe singleLinkListServe = new SingleLinkListServe();
 9         //直接添加
10         /*singleLinkListServe.addNode(heroNode1);
11         singleLinkListServe.addNode(heroNode2);
12         singleLinkListServe.addNode(heroNode3);
13         singleLinkListServe.addNode(heroNode4);*/
14         //有序添加
15         singleLinkListServe.addByOrder(heroNode1);
16         singleLinkListServe.addByOrder(heroNode2);
17         singleLinkListServe.addByOrder(heroNode4);
18         singleLinkListServe.addByOrder(heroNode3);
19         singleLinkListServe.printList();
20         System.out.println("————————————————————————————————————————————————————————————————");
21        //更新
22         HeroNode updateNode = new HeroNode(4,"林冲冲","豹子头大哥");
23         singleLinkListServe.update(updateNode);
24         singleLinkListServe.printList();
25         System.out.println("————————————————————————————————————————————————————————————————");
26         //删除
27         singleLinkListServe.delNode(4);
28         singleLinkListServe.printList();
29     }
30 }

 

五、反转单链表

 1 //单链表反转
 2     public HeroNode turnNode(){
 3         HeroNode head = headNode;
 4         if(head.nextNode == null || head.nextNode.nextNode == null){
 5             return head;
 6         }
 7         HeroNode curr = head;
 8         HeroNode prev = null;
 9 
10         while(curr != null){
11             HeroNode next = curr.nextNode;
12             curr.nextNode = prev;
13             prev = curr;
14             curr = next;
15         }
16 
17         return prev;
18 
19     }
20     //遍历反转链表
21     public void printList(HeroNode headNode){
22         //创建一个临时节点
23         HeroNode tempNode = headNode;
24         while(tempNode !=null){
25             if(tempNode.nextNode != null){
26                 System.out.println(tempNode);
27             }
28             tempNode = tempNode.nextNode;
29         }
30     }

 

六、利用栈反转输出

 1 //从尾到头打印单链表(不改变链表结构)
 2     public void printListUseStack(){
 3 
 4         HeroNode tempNode = headNode;
 5 
 6         Stack<HeroNode> stack = new Stack<>();
 7         
 8         if(tempNode.nextNode == null){
 9             System.out.println("链表为空");
10             return;
11         }
12         
13         while(tempNode.nextNode != null){
14             //将获取的数据放入栈中
15             stack.push(tempNode.nextNode);
16             tempNode = tempNode.nextNode;
17         }
18         while(stack.size()>0){
19             //从栈中输出
20             System.out.println(stack.pop());
21         }
22 
23     }

 

posted @ 2022-05-05 15:54  jason饼干大怪兽  阅读(57)  评论(0)    收藏  举报