数据结构练习---单向链表

单向链表基础:

/**
 * 单向链表
 * @author 12640
 */
public class ListNode {
    private int data;
    private ListNode next;

    public int getData() {
        return data;
    }

    public ListNode getNext() {
        return next;
    }

    public void setNext(ListNode next) {
        this.next = next;
    }

    public void setData(int data) {
        this.data = data;
    }

    /**
     * 返回链表的节点长度
     * int类型
     * @return
     */
    public int ListLength(ListNode headNode){
        int length=0;
        ListNode currentNode=headNode;
        while(currentNode!=null){
            length++;
            currentNode = currentNode.next;
        }
        return length;
    }

    /**
     * 向指定位置插入链表节点
     * 链表看似简单,但是注意链表对象只是一个对象,存储的信息包括Value和NextNode的信息
     * 头部插入效率最高
     * 所以HashMap中发生碰撞是头部插入
     * @param headNdoe
     * @param nodeToInsert
     * @param position
     * @return
     */
    public ListNode insertListNode(ListNode headNdoe,ListNode nodeToInsert,int position){
        if(headNdoe==null){
            return nodeToInsert;
        }
        int size=ListLength(headNdoe);
        if(position>size+1||position<1){
            System.out.println("无效插入位");
            return headNdoe;
        }
        //头部插入情况,时间复杂度为1
        if(position==1){
            //直接将插入的链表节点的下一个设为headNode
            nodeToInsert.setNext(headNdoe);
            return nodeToInsert;
        }else {
            ListNode preNode=headNdoe;
            int count=1;
            while (count<position-1){
                preNode=preNode.getNext();
                count++;
            }
            ListNode nextNode = preNode.getNext();
            nodeToInsert.setNext(nextNode);
            preNode.setNext(nodeToInsert);
        }
        return headNdoe;
    }

    /**
     * 删除确定位置的节点
     * @param headNode
     * @param position
     * @return
     */
    public ListNode DeleteNode(ListNode headNode,int position){
        int size=ListLength(headNode);
        if(position >size|| position<1){
            System.out.println("删除越界");
            return headNode;
        }
        if(position == 1){
            ListNode nextNode=headNode.getNext();
            headNode=null;
            return nextNode;
        }else {
            ListNode preNode=headNode;
            int count=1;
            while(count<position){
                preNode = preNode.getNext();
                count++;
            }
            ListNode nextNode= preNode.getNext();
            //跳过nextNode,相当于删除
            preNode.setNext(nextNode.getNext());
            nextNode = null;
        }
        return headNode;
    }

    /**
     * 删除整个链表,用一个迭代器实现不断循环下一个
     * 同时将当前的ListNode设为NULL
     * @param head
     */
    public void DeleteListNode(ListNode head){
        ListNode auxilaryNode,iterator=head;
        while (iterator != null){
            auxilaryNode = iterator.getNext();
            iterator = null;
            iterator = auxilaryNode;
        }
    }
    /**
     * add方法,尾部添加一个链表
     */
    public void addListNode(int val,ListNode head){
        while (head.next!=null){
            head=head.next;
        }
        ListNode addOne=new ListNode();
        addOne.data=val;
        head.next=addOne;
    }

    /***
     * 批量增加
     */
    public void addLotListNode(int[] nums,ListNode head){
        while (head.next!=null){
            head=head.next;
        }
        ListNode addOne=new ListNode();
        head.next=addOne;
        for(int i=0;i<nums.length;i++){
            addOne.data=nums[i];
            addOne.next=new ListNode();
            addOne=addOne.next;
        }
    }
    /***
     * 反转链表并输出
     */
    public static void reverseListNode(ListNode head){
        if(head.next!=null) {
            reverseListNode(head.next);
            head.next.next = head;
            System.out.println(head.data);
        }
        head.next=null;

    }

  
}

单向链表有关问题

  1. 找到链表倒数第N个点
    方法一:蛮力法,经过两次遍历。
    方法二:散列表法,建立一个HashMap,存储值与节点,返回Length-n的key的节点
    方法三:双指针,一个指针在另一个指针出发n格后出发,这样当前指针到头后,后指针指向N
  2. 判定节点是以NULL结尾,还是形成了一个环
    方法一:定义一个Lsit<>放入ListNode,如果有null则无环,如果有list.contain则有环
    方法二:Floyd环判定算法,利用两个快慢不一的指针,如果相遇则存在环
public boolean DoesLinkedLsitContainsLoop(ListNode head){
        if(head == null){
            return false;
        }
        ListNode slowPtr=head;
        ListNode fastPtr=head;
        while (fastPtr.next!=null && fastPtr.next.next!=null){
            slowPtr=slowPtr.next;
            fastPtr=fastPtr.next.next;
            if(fastPtr==slowPtr){
                return true;
            }
        }
        return false;
    }
  1. 在有序链表中插入一个节点。
 /**
     * 在有序链表中插入某一个链表
     * @param head
     * @param newNode
     * @return
     */
    public ListNode InsertInSortedList(ListNode head,ListNode newNode){
        ListNode current = head;
        if(head == null){
            return newNode;
        }
        ListNode temp = current;
        while (current!=null && current.getData()<newNode.getData()){
             temp = current;
            current=current.next;
        }
        newNode.next=current;
        temp.next=newNode;
        return head;
    }
  1. 逆置单向链表
    public ListNode ReverseList(ListNode head){
        ListNode temp=null;
        ListNode nextNode=null;
        while (head!=null){
            nextNode=head.getNext();
            head.next=temp;
            temp=head;
            head=nextNode;
        }
        return temp;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值