java单向链表的实现以及多段反转

java的单向链表的实现以及反转是很多面试官喜欢出的题目,java的链表结构是什么样的?
链表是由一个指向下一个节点的next指针,以及一个node节点。
在这里插入图片描述
链表的操作也是很有局限性的,查找元素只能从头节点一直往下,直达找到对应的节点为止。
链表的反转未采用递归是为了更好的理解链表的操作以及链表的查询原理
根据链表的定义我们将操作划分为四大类:插入,删除,查找,替换。
单项链表的实现

class LinkNode<T> {
    private Node head;//头结点
    private int count=0;//结点数目
    private int foot;//相当于内部节点的index
    private class Node{//内部类实现外部方法的桥梁
        private T data;
        private Node next;
        public Node(T data){
            this.data=data;
        }
        private void add(T value){
            if(this.next==null){
                this.next=new Node(value);//添加新节点
            }else{
                this.next.add(value);//递归到末尾
            }
        }
        private void remove(Node privious,int index){//@privious 目标节点的上一个节点
            if(LinkNode.this.foot++==index){//即使判断当前节点的索引是否等于指定节点,foot外部类指定。
                privious.next=this.next;
                this.next=null;
                LinkNode.this.count--;
                return;
            }else{
                this.next.remove(this,index);//递归到指定节点
            }
        }
        private void remove(Node previous,T data){//删除
            if(this.data.equals(data)){
                previous.next=this.next;
                this.next=null;
                LinkNode.this.count--;
            }else {
                if (this.next != null) {
                    this.next.remove(this,data);
                }else{return;}
            }
        }

        private void replace(T oldData,T newData){//替换
            if(this.data.equals(newData)){
                this.data=newData;
            }else{
                this.next.replace(oldData,newData);
            }
        }

        public void replace(int index,T newData){
            if(LinkNode.this.foot++==index){
                this.data=newData;
            }else this.next.replace(index,newData);

        }
        public T get(int index){//获取
            if(LinkNode.this.foot++==index){
                return this.data;
            }
            else{
                return this.next.get(index);
            }
        }
        public boolean contains(T data) {
            if (this.data.equals(data)) return true;
            else {
                if (this.next != null) {
                    return this.next.contains(data);
                } else {
                    return false;
                }
            }
        }
    }

    public LinkNode(){}
    public boolean contains(T data) {
        if (this.isEmpty()) return false;
        else {
            return  this.head.contains(data);
        }
    }

    public boolean isEmpty(){
        if(count == 0 || this.head == null){
            return true;
        }else{
            return false;
        }
    }
    public void add(T data){
        if(this.isEmpty()){
            this.head=new Node(data);
        }
        else {
            this.head.add(data);
        }
        this.count++;
    }
    public void remove(int index){
        if(this.isEmpty()){
            return;
        }
        if(index<0||this.count<=index){
            return;
        }
        if(index==0){
            Node temp=this.head;
            this.head=this.head.next;
            temp.next=null;
            this.count--;
            return;
        }
        else{
            this.foot=0;
            this.head.remove(this.head,index);
        }
    }
    public void remove(T data){
        if(this.isEmpty()){
            return;
        }
        if(this.head.data.equals(data)){
            Node temp=this.head;
            this.head=this.head.next;
            temp.next=null;
            this.count--;
            return;
        }else{this.head.remove(this.head,data);}
    }
    public void replace(int index,T newData){
        if(this.isEmpty())return;
        if(index<0||this.count<=index)return;
        this.foot=0;
        this.head.replace(index,newData);

    }
    public void replace(T oldData,T newData){
        if(this.isEmpty())return;
        this.head.replace(oldData,newData);//交给内部类处理
    }
    public T get(int  index){
        if(this.isEmpty()){
            return null;
        }
        this.foot=0;
        return this.head.get(index);
    }
    public Object[] toArray(){//遍历
        if(this.isEmpty()){
            return null;
        }
        int count = this.count;
        Object[] retVal = new Object[count];
        for(int i=0;i<count;i++){
            retVal[i] = this.get(i);
        }
        return retVal;
    }
    //@param k 步长
    //@param link 需要反转的链表
    public void rkNode(LinkNode link,int k){
        for(int j=0;j<link.count-1;j++){//对每一个链表的元素进行判断
            if((j+1)/k<(link.count/k)){//以k为步长选取每一段
                if((j+1)%k!=0)//每一段首个元素不需要进行反转
                    link.rK((j+1)/k*k,j);
            }
        }
    }
    public void rK(int start ,int index){//对2个元素反转
        if(start==0){//如果为首节点反转
            Node pre=head;//pre 为目标节点的上一个节点
            for(int i=0;i<=index-1;i++){
                pre=pre.next;
            }
            Node cur=pre.next;//目标节点
            Node next=cur.next;//目标节点的尾链
            cur.next=head;//将目标节点定为首节点
            pre.next=next;//连接尾节点
            this.head=cur;//更新首节点
        }
        else{//非首节点反转
            Node lpre=null;//开始节点的首节点
            Node heads=head;
            for(int i=0;i<start-1;i++){
                heads=heads.next;
            }//找到开始节点的上一个节点
            lpre=heads;
            Node starts=lpre.next;//指定开始节点即是start
            Node rcur=starts;
            for(int i=start;i<index;i++){
                rcur=rcur.next;
            }//遍历找到目标节点的上一个节点
            Node rcurs=rcur.next;//获得目标节点
            Node next=rcurs.next;//获得目标节点的下一个节点
            rcurs.next=starts;//指定目标节点为这一段的首节点
            lpre.next=rcurs;//将开始节点的上一段与开始节点连接起来
            rcur.next=next;//将目标节点的下一段与目标节点连接
        }

    }

测试:

 public static void main(String[] args){

         LinkNode<Integer> mylink=new LinkNode<Integer>();
        mylink.add(1);
        mylink.add(2);
        mylink.add(3);
        mylink.add(4);
        mylink.add(5);
        mylink.add(6);
        mylink.add(7);
        mylink.add(8);
        mylink.rkNode(mylink,4);
        Object[] myint=mylink.toArray();
        System.out.println("链表长度:"+myint.length);
        for(Object in:myint){
            System.out.println(in);
        }

测试结果:
长度8:
k=4
在这里插入图片描述
k=3
在这里插入图片描述
参考文档:https://blog.csdn.net/zhangcongyi420/article/details/88259722

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值