数据结构 单链表的反转

数据结构 单链表的反转

在这里插入图片描述

单链表简介

在这里插入图片描述

单链表的反转(Java实现)

定义节点与链表

示意图
节点类

在这里插入图片描述

链表

在这里插入图片描述

实现步骤

  • 思路:
  1. 先定义一个节点 reverseHead = new HeroNode();
  2. 从头到尾遍历原来的链表,每遍历一个节点,就将其取出,并放在新的链表reverseHead 的最前端.
  3. 原来的链表的head.next = reverseHead.next

关键部位代码

   //单链表的反转方式二
    public static void reverseList1(HeroNode head) {
        //链表为空或者链表只有一个节点,无需反转
        if (head.next == null || head.next.next == null) {
            return;
        }
        //定义辅助变量
        HeroNode cur = head.next;
        //存放原链表当前节点的下一个节点
        HeroNode next = null;
        //反转列表头节点
        HeroNode reverseHead = new HeroNode();
        while (cur != null) {//遍历原列表将数据根据头插法插入新链表
            //保存原链表当前节点的下一个节点
            next = cur.next;
            //将当前节点插入反转链表
            cur.next = reverseHead.next;
            reverseHead.next = cur;
            //将辅助节点指向原链表下一个节点
            cur = next;
        }
        //将反转链表头节点赋给原头节点
        head.next = reverseHead.next;
    }
内存示意图

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
最终得到:
在这里插入图片描述

易错点

  • 代码实现步骤容易出错误的地方:当我们使用辅助节点遍历原单链表的时候,会忘记保存辅助节点的下一个节点,导致原单链表节点的丢失。
  • 代码如下:

注意:这是错误的代码

   //单链表的反转方式二
    public static void reverseList1(HeroNode head) {
        //链表为空或者链表只有一个节点,无需反转
        if (head.next == null || head.next.next == null) {
            return;
        }
        //定义辅助变量
        HeroNode cur = head.next;
        //反转列表头节点
        HeroNode reverseHead = new HeroNode();
        while (cur != null) {//遍历原列表将数据根据头插法插入新链表
            //将当前节点插入反转链表
            cur.next = reverseHead.next;
            reverseHead.next = cur;
            //错误❌ :原意为获取原来单链表的下一个节点,但由于该节点指向已经改变,因此发生错误
            cur = cur.next;
            
        }
        //将反转链表头节点赋给原头节点
        head.next = reverseHead.next;
    }
错误代码内存示意图:

在这里插入图片描述

完整代码

public class SingleLinkedListDemo {
    public static void main(String[] args) {
        HeroNode h1 = new HeroNode(1,"宋江", "及时雨");
        HeroNode h2 = new HeroNode(2,"卢俊义", "玉麒麟");
        HeroNode h3 = new HeroNode(3,"吴用", "智多星");
        HeroNode h4 = new HeroNode(4,"林冲", "豹子头");

        //创建一个链表
        SingleLinkedList singleLinkedList = new SingleLinkedList();

        singleLinkedList.addByOrder(h1);
        singleLinkedList.addByOrder(h2);
        singleLinkedList.addByOrder(h4);
        singleLinkedList.addByOrder(h3);

        singleLinkedList.show();
        /*
        HeroNode{no=1, name='宋江', nickName='及时雨'}
        HeroNode{no=2, name='卢俊义', nickName='玉麒麟'}
        HeroNode{no=3, name='吴用', nickName='智多星'}
        HeroNode{no=4, name='林冲', nickName='豹子头'}
         */

        System.out.println("****************************");
        //测试单链表反转
//        HeroNode newHead = reverseList(singleLinkedList.getHead());
//        singleLinkedList.setHead(newHead);
//        singleLinkedList.show();
        reverseList1(singleLinkedList.getHead());
        singleLinkedList.show();

    }

    //单链表的反转方式二
    public static void reverseList1(HeroNode head) {
        //链表为空或者链表只有一个节点,无需反转
        if (head.next == null || head.next.next == null) {
            return;
        }
        //定义辅助变量
        HeroNode cur = head.next;
        //存放原链表当前节点的下一个节点
        HeroNode next = null;
        //反转列表头节点
        HeroNode reverseHead = new HeroNode();
        while (cur != null) {//遍历原列表将数据根据头插法插入新链表
            //保存原链表当前节点的下一个节点
            next = cur.next;
            //将当前节点插入反转链表
            cur.next = reverseHead.next;
            reverseHead.next = cur;
            //将辅助节点指向原链表下一个节点
            cur = next;
        }
        //将反转链表头节点赋给原头节点
        head.next = reverseHead.next;
    }

    //单链表的反转【腾讯面试题,有点难度
    public static HeroNode reverseList(HeroNode head) {
        if (head.next == null || head.next.next == null) {
            return head;
        }
        //定义辅助变量,遍历链表
        HeroNode temp = head;
        //新建一个头节点,保存反转链表
        HeroNode newHead = new HeroNode();

        while (true) {
            if (temp.next == null) {
                break;
            }
            temp = temp.next;
            HeroNode newTemp = new HeroNode(temp.no, temp.name, temp.nickName);
            if (newHead.next == null) {
                newHead.next = newTemp;
                newTemp.next = null;
            } else {
                //temp变量指针不能变,定义辅助变量,给新链表赋值
                newTemp.next = newHead.next;
                newHead.next = newTemp;
            }
        }
        return newHead;
    }

 
 

}


//定义SingleLinkedList 管理我们的英雄
class SingleLinkedList {
    //初始化头节点
    private HeroNode head = new HeroNode();

    //返回头节点
    public HeroNode getHead() {
        return head;
    }

    //给头节点赋值
    public void setHead(HeroNode head) {
        this.head = head;
    }

    //添加数据
    // 第一种方法:,直接添加到链表的尾部
    public void add(HeroNode heroNode) {
        //因为head节点不能移动,定义辅助变量
        HeroNode temp = getHead();
        //遍历链表,找到末节点
        while (true) {
            if (temp.next == null) {
                break;
            }
            temp = temp.next;
        }
        temp.next = heroNode;

    }
	
    //添加数据
    //第二种方式:根据排名将英雄插入到指定位置
  public void addByOrder(HeroNode heroNode) { 
        //因为head节点不能移动,定义辅助变量
        HeroNode temp = getHead();
        boolean flag = false;// flag标志添加的编号是否存在,默认为false
        //遍历链表,找到相应节点
        while (true) {
            if (temp.next == null) {
                break;
            } else if (temp.next.no > heroNode.no) {
                break;
            } else if (temp.next.no == heroNode.no) {
                flag = true; //说明编号存在
                break;
            }
            temp = temp.next;//后移,遍历当前链表
        }
        if (flag) {
            System.out.println("已存在");
        } else {//插入到链表中, temp的后面
            heroNode.next = temp.next;
            temp.next = heroNode;
        }
    }

    //遍历链表
    public void show() {
        //判断链表是否为空
        if(head.next == null) {
            System.out.println("链表为空");
            return;
        }
        HeroNode temp = getHead();
        //遍历链表,找到末节点
        while (true) {
            if (temp.next == null) {
                break;
            }
            //将temp后移
            temp = temp.next;
            System.out.println(temp);
        }

    }

    //根据编号删除数据
    public void delete(int no) {
        HeroNode temp = getHead();
        while (true) {
            if (temp.next == null) {
                break;
            }
            if (temp.next.no == no) {
                //找到的待删除节点的前一个节点temp
                temp.next = temp.next.next;
                System.out.println("删除成功");
                return;
            }
            temp = temp.next;
        }
        System.out.println("没有找到相应数据");

    }

    //根据编号修改数据
    public void update(HeroNode heroNode) {
        //判断是否空
        if(head.next == null) {
            System.out.println("链表为空~");
            return;
        }
        //找到需要修改的节点, 根据no编号
        //定义一个辅助变量
        HeroNode temp = getHead();
        boolean flag = false;//表示是否找到该节点
        while (true) {
            if (temp.next == null) {
                break;//已经遍历完链表
            }
            if (temp.no == heroNode.no) {
                temp.name = heroNode.name;
                temp.nickName = heroNode.nickName;
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag) {
            System.out.println("修改成功");
        } else {
            System.out.println("没有找到数据");
        }
    }

    //根据编号查询数据
    public HeroNode get(int no) {
        //判断是否空
        if(head.next == null) {
            System.out.println("链表为空~");
            return null;
        }
        HeroNode temp = getHead();
        while (true) {
            if (temp.next == null) {
                break;
            }
            if (temp.no == no) {
                return temp;
            }
        }
        return null;
    }

}


//定义HeroNode , 每个HeroNode 对象就是一个节点
class HeroNode {
    public int no;
    public String name;
    public String nickName;
    public HeroNode next;//指向下一个节点

    //构造器
    public HeroNode() {

    }

    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 + '\'' +
                '}';
    }
}

链表的详细资料请参考:Java数据结构与算法 day02 链表与栈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值