单向链表的常见操作

一、单向链表反转
/**
         * 这里要注意,我的head不能作为开始的第一个结点,我的head只是一个起点的哨兵标识
         * 如果将head作为第一个结点开始计算,
         * 假如单向链表结构为:  head -> a -> b -> c   lest = c;
         * 那么第一次运算之后head -> null
         * 第二次运算  a -> head
         * 第三次运算  b -> a
         * 第四次运算  c -> b
         * 跳出while循环,我们的操作是
         * head -> c
         * 此时就形成了一个循环,
         * a -> head -> c -> b -> a -> head -> c  ........  如果我们要打印这个单向链表就容易出现StackOverflowError!
         */
        Node<E> begin = null;
        Node<E> model = this.head.getNext();
        this.last = model;
        Node<E> end = model.getNext();
        while (true){
            model.setNext(begin);
            if(end == null){
                break;
            }
            begin = model;
            model = end;
            end = end.getNext();
        }
        this.head.setNext(model);
        return;
    }

注意这个方法是放在我之前的LinkNode类中。博客地址
这里使用的是3个指针,每循环一次,3个指针都移动一次,并且改变model结点的指针方法,这种单向链表反转也叫做原地反转!

二、判断链表中是否有环。

思路:
1、快慢指针方法,使用两个指针,同时进行移动,如果链表中有环,那么这两个指针会先后进入环中,因为一个走的慢,一个走的快,总有一此循环会导致这两个指针是指向同一个结点!
2、足迹法,首先建立一个Map用来存储链表中的结点,然后遍历这个链表,每遍历一次就把结点信息保存到Map中,如果Map中存储了重复了元素则说明链表中有环!
我实现了快慢指针法如下:

    /**
     * 快慢指针法判断链表中是否有环
     * @return
     */
    public boolean isHaveLoop(){
        if(this == null){
            return false;
        }
        Node<E> p = this.head.getNext();//第一个结点
        Node<E> q = this.head.getNext().getNext();//如果有的话是第二个结点
        //如果q为空,那么这个单向链表只有一个结点,肯定不会形成环
        //如果q不为空,并且q的下一个结点为空,那么有两个结点并且第二个结点指向null,肯定也不会形成环
        while (q != null && q.getNext() != null){
            p = p.getNext();
            q = q.getNext().getNext();

            if(q == null){
                return false;
            }else if(p == q){
                return true;
            }
        }
        return false;
    }

注意:这个方法也是放在了我上一篇博客中的LinkNode类中。博客地址

三、使用递归来实现两个有序单向链表合并
public class LinkNodes {


    /**
     * 使用递归来实现两个有序单向链表合并
     * @param node1
     * @param node2
     * @return
     */
    public static Node<Integer> mergeLinkNode(Node<Integer> node1,Node<Integer> node2){
        //当node1和node2同时为null时,说明到node1和node2的最后一个结点。
        if(node1 == null && node2 == null){
            return null;
        }
        //node1为null则不用再比较大小了
        if(node1 == null){
            return node2;
        }
        if(node2 == null){
            return node1;
        }
        Node<Integer> node = new Node<>();
        if(node1.getE() > node2.getE()){
            node = node2;
            node.setNext(mergeLinkNode(node1,node2.getNext()));
        }else if(node1.getE() < node2.getE()){
            node = node1;
            node.setNext(mergeLinkNode(node1.getNext(),node2));
        }else{
            node = node1;
            node.setNext(mergeLinkNode(node1.getNext(),node2.getNext()));
        }
        return node;
    }

}

注意:这个是我新建了一个工具类,为了方便起见,我将泛型执行为了Integer
下面是我的测试

public class TestLinkNode {

    public static void main(String[] args) {
        Node<Integer> node = new Node<>(1);
        Node<Integer> node1 = new Node<>(2);
        Node<Integer> node2 = new Node<>(3);
        Node<Integer> node3 = new Node<>(4);
        Node<Integer> node4 = new Node<>(5);
        Node<Integer> node5 = new Node<>(6);
        Node<Integer> node6 = new Node<>(7);
        Node<Integer> node7 = new Node<>(8);

        node.setNext(node2);
        node2.setNext(node4);
        node4.setNext(node6);
        node6.setNext(node7);
        System.out.println("----------第一个有序单向链表------------");
        System.out.println(node);

        node1.setNext(node3);
        node3.setNext(node5);
        System.out.println("----------第二个有序单向链表------------");
        System.out.println(node1);

        Node<Integer> node8 = LinkNodes.mergeLinkNode(node, node1);
        System.out.println("----------两个有序单向链表合并之后------------");
        System.out.println(node8);

    }
}

输出:

----------第一个有序单向链表------------
Node{next=Node{next=Node{next=Node{next=Node{next=null, e=8}, e=7}, e=5}, e=3}, e=1}
----------第二个有序单向链表------------
Node{next=Node{next=Node{next=null, e=6}, e=4}, e=2}
----------两个有序单向链表合并之后------------
Node{next=Node{next=Node{next=Node{next=Node{next=Node{next=Node{next=Node{next=null, e=8}, e=7}, e=6}, e=5}, e=4}, e=3}, e=2}, e=1}

Process finished with exit code 0

结束!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值