常用链表的操作

常用链表的操作:

 单链表反转
* 链表中环的检测
* 两个有序的链表合并
* 删除链表倒数第 n 个结点
* 求链表的中间结点

 

public class LinkedNode {

    public Node<Integer> getHeader() {
        return header;
    }

    private Node<Integer> header;

    /**
     * 添加节点
     *
     * @param val
     */
    public void addNode(int val) {
        if (null == header) {
            //一开始是没有后面的节点的
            header = new Node<Integer>(val, null);
            return;
        }
        //每次添加的时候总是往最前面添加,单链表的结构就是不论从前往后还是从后往前都是添加到第一个了,也就是只有第一个才能开始查找起来
        header = new Node<Integer>(val, header);
    }


    /**
     * 这是先进后出的一种添加链表的方式
     * @param val
     * @param header
     * @return
     */
    public Node<Integer> addNameNode(int val, Node<Integer> header) {
        if (null == header) {
            header = new Node<>(val, null);
            return header;
        }
        header = new Node<>(val, header);
        return header;
    }


    public void addNode(int val, Node<Integer> header){
        if (null == header) {
            header = new Node<>(val, null);
        }
        Node<Integer> newNode=new Node<>(val,null);
        Node<Integer> p=header;
        while(true){
            if(null==p.getNext()){
            p.setNext(newNode);
            break;
            }
            p=p.next;
        }
    }


    /**
     * 单链表反转
     *
     * @param header
     * @return
     */
    public Node<Integer> reverseLink(Node<Integer> header) {
        if (null == header || null == header.getNext()) {
            return header;
        }
        Node<Integer> cur = header.getNext();
        Node<Integer> pre = header;
        while (null != cur) {
            //先把下一个节点临时存起来
            Node<Integer> next = cur.getNext();
            //这一行才是核心,就是把next的指针从下一个  换成上一个
            cur.setNext(pre);
            //把上一个指针挪到当前的,准备下一个
            pre = cur;
            //把当前的指针挪到下一个,准备下一次呼唤
            cur = next;
        }
        //这个时候需要把一开始的头节点置空,不然就会出现循环引用的情况,因为改变之后的倒数第二个节点的next和原来的header形成相互引用
        header.setNext(null);
        return pre;
    }

    /**
     * 核心就是每次从最后一个加到第一个,然后不断地删掉多加的,和之前的循环不太一样的
     *
     * @param header 每次递归获得的header都是一个节点的引用
     * @return
     */
    public Node<Integer> reverseLinked2(Node<Integer> header) {
        if (null == header || null == header.getNext()) {
            //这一步是最核心的,因为新的节点起点从这里开始
            return header;
        }
        //最后一个节点调用的时候最先返回的是最后一个节点,这个node引用是从之前的最后一个节点开始记录的,不断的添加新的节点每次添加一个header,而header执行到最后的时候其实是之前的第一个个节点
        Node<Integer> Node = reverseLinked2(header.getNext());

        //从倒数第二次递归开始获得的值,也就是倒数第二个节点要想给最后一个节点后面加值,就只能这样设置,最后一个节点的next设置为倒数第二个节点
        header.getNext().setNext(header);
        //这样的话,每次都是添加的header这个引用的这样一个几点
        header.setNext(null);

        return Node;
    }

    public void iterate(Node<Integer> header) {
        if (null == header) {
            return;
        }
        Node<Integer> next = header;
        while (null != next) {
            System.out.print("  " + next.getVal());
            next = next.getNext();
        }
    }


    /**
     * 链表中环的检测
     *
     * @param header
     * @return
     */
    public boolean hasLoop(Node<Integer> header) {
        Node<Integer> slowPoint = header;
        Node<Integer> fastPoint = header.getNext();
        while (null != fastPoint && null != fastPoint.getNext()) {
            slowPoint = slowPoint.getNext();
            fastPoint = fastPoint.getNext().getNext();
            if (null == fastPoint) {
                return false;
            }
            if (slowPoint.equals(fastPoint)) {
                return true;
            }
        }
        return false;
    }


    /**
     * 有序链表的合并
     *
     * @return
     */
    public Node<Integer> mergeLinked(Node<Integer> n1, Node<Integer> n2) {
        Node<Integer> guard = new Node<>(-1, null);
        //定义两个指针记录两个链表的走的位置
        Node<Integer> p1 = n1;
        Node<Integer> p2 = n2;
        //定义一个指针定义当前的位置
        Node<Integer> curNode = guard;
        while (null != p1 && null != p2) {
            if (p1.getVal() > p2.getVal()) {
                curNode.setNext(p1);
                p1 = p1.getNext();
            } else {
                curNode.setNext(p2);
                p2 = p2.getNext();
            }
            curNode = curNode.getNext();
        }
        return guard.getNext();
    }

    /**
     *  递归的就是从最后一个的返回值出发,然后进行,递归就是一定要有返回值,每次都去操作这个返回值
     * @param n1
     * @param n2
     * @return
     */
    public Node<Integer> mergeList(Node<Integer> n1, Node<Integer> n2){
       if(null==n1){
           return n2;
       }
       if(null==n2){
           return n1;
       }
       if(n1.getVal()>n2.getVal()){
           n1.next=mergeList(n1.getNext(),n2);
           return n1;
       }else{
           n2.next=mergeList(n1,n2.next);
           return n2;
       }

    }


    /**
     * 删除倒数第n个节点
     * @param n
     * @param num
     * @return
     */
   public Node<Integer> removeLastNode(Node<Integer> n,int num){
       //思路就是1、首先找到倒数第n个节点,有两个办法,一个是直接把当前的单链表反转过来,顺着数到第n个
       //思路2 西安遍历到最后一个,然后从最后一个开始
       Node<Integer> pre = getIntegerNode(n);
       Node p=pre;

       int count=0;
       while(true){
           count++;
           if(count==num){
            p.next=p.next.next;
            break;
           }
           p=p.next;
       }
       Node<Integer> integerNode = getIntegerNode(pre);
       return integerNode;
   }

    private Node<Integer> getIntegerNode(Node<Integer> n) {
        Node<Integer> pre=null;
        Node<Integer> cur=n;
        while(null!=cur){
             Node temp=cur.getNext();
             cur.setNext(pre);
             pre=cur;
             cur=temp;
        }
        return pre;
    }


    /**
     * part就相当于一个指针一样的
     * @param n1
     * @param num
     * @return
     */
    Node<Integer> removeList(Node<Integer> n1,int num){
       Node<Integer> header=new Node<>(-1,null);
       Node<Integer> part=n1;
       Node<Integer> all=n1;
        header.next=n1;
       while(null!=part&&num>=0){
           part=part.next;
           num--;
       }

       while(null!=part){
           part=part.next;
           all=all.next;
       }
       all.next=all.next.next;
       return header.next;
    }

    Node<Integer> findMiddleNode(Node<Integer> header){
        if(null==header){
            return header;
        }
        Node<Integer> fast=header;
        Node<Integer> slow=header;

        while(null!=fast){
            fast=fast.next.next;
            slow=slow.next;
        }
        return slow;
    }








}

接下来需要用到的就是写一个链表的实体类

class Node<T> {
    /**
     * 存放数据的地方
     */
    T val;

    /**
     * 存放引用的地方(C语言中的指针,意思差不多)
     */
    Node<T> next;

    public Node(T val, Node<T> next) {
        this.val = val;
        this.next = next;
    }

    public T getVal() {
        return val;
    }

    public Node<T> getNext() {
        return next;
    }

    public void setVal(T val) {
        this.val = val;
    }

    public void setNext(Node<T> next) {
        this.next = next;
    }
}

 

至此 所有的Java代码已经完成

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值