腾讯面试题:单链表的反转

要实现单链表的反转,我们首先需要创建一个单链表并实现CRUD操作,因我之前已写过类似的文章,故不再赘述,在此附上链接

创建单链表并实现CRUD

单链表反转的思路

首先我们创建一个新的辅助链表并获取其头结点,我们通过两个指针next,cur;cur指针指向当前遍历到的结点。next指针指向当前遍历到的结点的下一个结点。我们每遍历一个新的结点,就把这个结点放到新的这个头结点的最前面的位置,如此叠进,就能获得一个新的反转的单链表,最后再把head的next指向辅助链表的头结点的下一个结点。

下列是代码实现,要点在于创建一个新的链表,接用头结点

package com.liu.linkedlist;

/**
 * @author liuweixin
 * @create 2021-09-07 15:28
 */
//腾讯面试题,实现单链表的反转
public class TencentLinkedList {
    private Node2 head = new Node2("", 0);//头结点;

    public static void main(String[] args) {
        TencentLinkedList list = new TencentLinkedList();//创建一个链表
        System.out.println("反转前");
        list.addNode2(new Node2("a", 1));
        list.addNode2(new Node2("b", 2));
        list.addNode2(new Node2("c", 3));
        list.addNode2(new Node2("d", 4));
        list.addNode2(new Node2("e", 5));
        list.show();
        System.out.println("反转后");
        list.reverse();
        list.show();
    }

    /**
     * 反转链表的数据
     */
    public void reverse() {
        if (head.next == null || head.next.next == null) {
            System.out.println("该链表没有数据或只有一个结点");
            return;
        }
        Node2 cur = head.next;//指向第一个数据
        Node2 next = null;//指向cur的下一个结点,为了保存cur的下一个结点不被丢失
        TencentLinkedList reverse = new TencentLinkedList();//创建一个辅助链表,借用头结点
        Node2 reverseHead = reverse.getHead();//借用头结点
        while (cur != null) {
            next = cur.next;//保存cur的下一个结点
            cur.next = reverseHead.next;//把辅助链表的下一个结点赋给当前结点的下一个结点,实现辅助链表的一个后递
            reverseHead.next = cur;
            cur = next;//cur回归原链表
        }
        //循环结束,交换完毕,此时需把原链表的头结点指向辅助链表的第一个数据,这就实现了反转
        head.next = reverseHead.next;
    }

    /**
     * 获取头结点
     *
     * @return 返回头结点
     */
    public Node2 getHead() {
        return this.head;
    }

    /**
     * 获取链表的总数
     *
     * @return 返回链表的总数
     */
    public int getCount() {
        int count = 0;
        if (head.next == null) {//链表为空返回0
            return 0;
        }
        Node2 cur = head;//创建一个辅助结点
        while (cur.next != null) {//当cur的下一个结点不等于空时,count++,记录总数
            count++;
            cur = cur.next;//向下递换
        }
        return count;
    }

    /**
     * 添加结点
     *
     * @param Node2 要加入的结点
     */
    //对结点的操作放到链表中实现
    public void addNode2(Node2 Node2) {
        if (head.next == null) {
            //只有一个头结点,可以直接把数据加入到链表中
            head.next = Node2;
        } else {
            Node2 cur = head.next;//借助辅助结点去寻找到插入位置的前一个结点
            while (cur.next != null && cur.next.no < Node2.no) {//当cur.next.no>Node2.no时退出循环,此时已找到插入位置的前一个结点。
                //通过循环获取到插入位置的前一个结点
                cur = cur.next;//cur需要下移,才能找到合适的位置
            }
            if (cur.next == null) {//找到链表的最后仍然没有比插入结点的no值大的,直接添加到链表的最后
                cur.next = Node2;
                return;
            }
            //此时cur.next.no>Node2.no,即找到插入位置的前一个结点
            Node2.next = cur.next;//实现结点的传递
            cur.next = Node2;
        }
    }

    /**
     * 删除链表的结点
     *
     * @param no 结点数据的编号
     */
    public void deleteNode2(int no) {
        if (head.next == null) {
            System.out.println("链表为空,无法删除");
        } else {
            Node2 cur = head.next;//借助辅助结点去寻找到插入位置的前一个结点
            while (true) {
                if (cur.next == null) {//找到最后还没有找到删除的位置,说明该链表没有对应结点
                    System.out.println("链表无该节点,无法删除");
                    return;
                }
                if (cur.next.no == no) {
                    //此时已找到删除位置的前一个结点。
                    if (cur.next.next != null) { //删除结点的下一个结点不为空
                        cur.next = cur.next.next;
                    } else {//删除结点的下一个结点为空
                        cur.next = null;
                    }
                    return;//删除完成,结束方法
                }


                cur = cur.next;

            }
        }
    }

    /**
     * 更改结点信息
     *
     * @param Node2 要更改的结点
     */
    public void update(Node2 Node2) {
        if (head.next == null) {
            System.out.println("链表为空,无法更改");
        } else {
            Node2 cur = head;//借助辅助结点去寻找到插入位置的前一个结点
            while (true) {
                if (cur.next == null) {
                    if (cur.no != Node2.no) {
                        //找到最后还没有找到更新的位置,说明该链表没有对应结点
                        System.out.println("链表无该节点,无法更新");
                    }
                    return;
                }
                if (cur.next.no == Node2.no) {
                    //找到要更新的结点的前一个结点
                    if (cur.next.next != null) { //更新结点的下一个结点不为空
                        Node2.next = cur.next.next;
                        cur.next = Node2;//结点的移接
                    } else {//更新的结点是最后一个结点
                        cur.next = Node2;
                    }
                    return;
                }
                cur = cur.next;
            }

        }
    }


    /**
     * 遍历链表数据
     */
    public void show() {
        if (head.next == null) {
            System.out.println("该链表无数据");
            return;
        }
        Node2 cur = head.next;
        while (cur != null) {//注意这里的指针变化,这里的指针指的是当前遍历的结点,而不是遍历结点的前一个结点,这里跟上面添加和删除的临时结点不同
            System.out.println(cur);
            cur = cur.next;
        }
    }
}

class Node2 {//定义一个结点对象,每一个对象就是一个结点
    Node2 next;
    String name;
    int no;

    public Node2(String name, int no) {
        this.name = name;
        this.no = no;
    }

    @Override
    public String toString() {
        return "Node2{" +
                " name='" + name + '\'' +
                ", no=" + no +
                '}';
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值