单链表后篇-->(虚拟头)

dummyHead有了虚拟头结点,所有的位置都有前驱。
怎么头插?

当前链表有节点时:让当前的对象指向要插入数的结点,然后dummyHead指向当前对象就行了。

node.next=dummyHead.next;   dummyHead.next=node;

当前链表没结点时:

node.next=dummyHead.next;   dummyHead.next=node;

为什么一样的代码。

为什么一样的代码?因为虚拟头结点的存在大家都有前驱,因为当前链表没节点时:node.next=null,dummyHead.next=null 都是null。
有虚拟头结点后,所有结点都是该结点的“后继”,结点,无论当前是否存在有效元素,插入步骤一致,省去了判断头。

/**
 * 头插
 */
public class LinkedListWithHead {
    private  int size;
    private  Node dummyHead=new Node();

    public void addFirst(int val){

        Node node=new Node();
        node.val=val;
        node.next=dummyHead.next;
        dummyHead.next=node;
//        Node node=new Node(val,dummyHead.next);
//        dummyHead.next=node;

//        dummyHead.next=new Node(val,dummyHead.next);
        size++;
    }

 

关于任意位置的插入代码: 找前驱走index步
在索引为Index 的位置插入新节点value
add(2,20)在索引为2的地方插入200
prev指针是从dummyHead开始走走index步走到待插入位置的前驱结点
package seqlist;

/**
 * 初始化定义dummyHead
 */
public class LinkedListWithHead {
    private  int size;
    private  Node dummyHead=new Node();

    public class Node {
        int val;
        Node next;
 //    public Node(int val, Node next) {
//        
//    }
}
   //-------------插入部分--------------->
    /**
     * 头插
     */
    public void addFirst(int val){

        Node node=new Node();
        node.val=val;
        node.next=dummyHead.next;
        dummyHead.next=node;
//        Node node=new Node(val,dummyHead.next);
//        dummyHead.next=node;

//        dummyHead.next=new Node(val,dummyHead.next);
        size++;
    }

    /**
     * 在索引为Index 的位置插入新节点value
     * @param index
     * @param val
     */
    public void  add(int index,int val){
        if (index<0 || index >size){
            System.err.println(" add index illegal!");
            return;
        }
        Node prev=dummyHead;
        //prev 走index 步找到前驱,但是i会自己++
        for (int i = 0; i < index; i++) {
            prev=prev.next;
        }
        //此时prev到达指定位置
        /**
         * 写法1
         */
        Node node=new Node();
        node.val=val;
        node.next=prev.next;
        prev.next=node;
        size++;
        /**
         * 写法2
         */
//        //node 的值是val 后继结点就是prev.next,说的后继就是被插队的人
//        Node node=new Node(val,prev.next);
//        //然后让前驱指向node:
//        prev.next=node;
//        size++;
        /**
         * 写法3 其实就是匿名写法,让写法2合起来
         */
//        prev.next=new Node(val,prev.next);
//        size++;
    }
    public String toString(){
        String ret="";
        for (Node x=dummyHead.next; x!=null; x=x.next) {
            ret+=x.val;
            ret+="->";
        }
        ret+="null";
        return ret;
    }
package seqlist;

/**
 * 带头单链表的测试类
 */
public class LinkedListWithHeadTest {
    public static void main(String[] args) {
        //类的产生对象为LinkedListWithHead
        LinkedListWithHead linkedListWithHead=new LinkedListWithHead();
        linkedListWithHead.addFirst(3);
        linkedListWithHead.addFirst(1);
        linkedListWithHead.addFirst(5);
        System.out.println(linkedListWithHead);
        linkedListWithHead.add(1,2);
        linkedListWithHead.add(0,4);
        System.out.println(linkedListWithHead);
    }
}

5->1->3->null
4->5->2->1->3->null

有虚拟头的删除方法

找前驱走index步

//------------------删除部分----------->

    /**
     * 删除单链表中索引为index位置的结点,返回删除的结点值
     * @param index
     * @return
     */
    public int remove(int index){
        //1.索引的合法性
        if(rangCheck(index)){
            Node prev=dummyHead;
            //走Index步--->找到前驱
            for (int i = 0; i < index; i++) {
                prev=prev.next;
            }
            int oldValue=prev.next.val;
            //删除开始---->定义cur来存储删除结点地址
            Node cur=prev.next;
            prev.next=cur.next;
            cur.next=null;
            size--;
            return oldValue;
        }
        System.err.println("index illegal!");
        return -1;
    }

    private boolean rangCheck(int index) {
        if (index<0||index >=size){
            return false;
        }
        return true;
    }

package seqlist;

/**
 * 带头单链表的测试类
 */
public class LinkedListWithHeadTest {
    public static void main(String[] args) {
        //类的产生对象为LinkedListWithHead
        LinkedListWithHead linkedListWithHead=new LinkedListWithHead();
        linkedListWithHead.addFirst(3);
        linkedListWithHead.addFirst(1);
        linkedListWithHead.addFirst(5);
        linkedListWithHead.addFirst(7);
        linkedListWithHead.addFirst(6);
        linkedListWithHead.addFirst(8);
        System.out.println(linkedListWithHead);
        linkedListWithHead.remove(2);
        linkedListWithHead.remove(4);
        linkedListWithHead.remove(4);
        System.out.println(linkedListWithHead);
    }
}

index illegal!
8->6->7->5->1->3->null
8->6->5->1->null

全删(有虚拟头)
 /**
     * 删除所有值为val的结点
     * @param val
     */
    public void removeAllValue(int val){
        Node prev =dummyHead;
        while (prev.next !=null){
            if (prev.next.val==val){
                //找到了可以删除
                /**
                 * 写法1
                 */
//                Node x=prev.next;
//                prev.next=x.next;
//                x.next=null;
                /**
                 * 写法2
                 */
                prev.next=prev.next.next;
//一句话就删掉了,再加上prev.next.next=null就会异常;
//       错:        prev.next.next=null;
                size--;
            }else {
                //prev移动一定要放在else里
                //因为如果有多个val要都删完才能走prev
                prev = prev.next;
            }
        }
    }
package seqlist;

/**
 * 带头单链表的测试类
 */
public class LinkedListWithHeadTest {
    public static void main(String[] args) {
        //类的产生对象为LinkedListWithHead
        LinkedListWithHead linkedListWithHead=new LinkedListWithHead();
        linkedListWithHead.addFirst(1);
        linkedListWithHead.addFirst(1);
        linkedListWithHead.addFirst(1);
        linkedListWithHead.addFirst(1);
        linkedListWithHead.addFirst(1);
        linkedListWithHead.addFirst(1);
        linkedListWithHead.addFirst(1);
        System.out.println(linkedListWithHead);
        System.out.println("------删除1----------");
        linkedListWithHead.removeAllValue(1);
        System.out.println(linkedListWithHead);
    }
}

输出

1->1->1->1->1->1->1->null
------删除1----------
null

all代码

package seqlist;

/**
 * 初始化定义dummyHead
 */
public class LinkedListWithHead {
    private  int size;
    private  Node dummyHead=new Node();

    public class Node {
        int val;
        Node next;}


    //-------------插入部分--------------->
    /**
     * 头插
     */
    public void addFirst(int val){

        Node node=new Node();
        node.val=val;
        node.next=dummyHead.next;
        dummyHead.next=node;
//        Node node=new Node(val,dummyHead.next);
//        dummyHead.next=node;

//        dummyHead.next=new Node(val,dummyHead.next);
        size++;
    }

    /**
     * 在索引为Index 的位置插入新节点value
     * @param index
     * @param val
     */
    public void  add(int index,int val){
        if (index<0 || index >size){
            System.err.println(" add index illegal!");
            return;
        }
        Node prev=dummyHead;
        //prev 走index 步找到前驱,但是i会自己++
        for (int i = 0; i < index; i++) {
            prev=prev.next;
        }
        //此时prev到达指定位置
        /**
         * 写法1
         */
        Node node=new Node();
        node.val=val;
        node.next=prev.next;
        prev.next=node;
        size++;
        /**
         * 写法2
         */
//        //node 的值是val 后继结点就是prev.next,说的后继就是被插队的人
//        Node node=new Node(val,prev.next);
//        //然后让前驱指向node:
//        prev.next=node;
//        size++;
        /**
         * 写法3 其实就是匿名写法,让写法2合起来
         */
//        prev.next=new Node(val,prev.next);
//        size++;
    }
    //--------------------------------
    public String toString(){
        String ret="";
        for (Node x=dummyHead.next; x!=null; x=x.next) {
            ret+=x.val;
            ret+="->";
        }
        ret+="null";
        return ret;
    }



    //------------------删除部分----------->

    /**
     * 删除单链表中索引为index位置的结点,返回删除的结点值
     * @param index
     * @return
     */
    public int remove(int index){
        //1.索引的合法性
        if(rangCheck(index)){
            Node prev=dummyHead;
            //走Index步--->找到前驱
            for (int i = 0; i < index; i++) {
                prev=prev.next;
            }
            int oldValue=prev.next.val;
            //删除开始---->定义cur来存储删除结点地址
            Node cur=prev.next;
            prev.next=cur.next;
            cur.next=null;
            size--;
            return oldValue;
        }
        System.err.println("index illegal!");
        return -1;
    }

    private boolean rangCheck(int index) {
        if (index<0||index >=size){
            return false;
        }
        return true;
    }

    /**
     * 删除所有值为val的结点
     * @param val
     */
    public void removeAllValue(int val){
        Node prev =dummyHead;
        while (prev.next !=null){
            if (prev.next.val==val){
                //找到了可以删除
                /**
                 * 写法1
                 */
//                Node x=prev.next;
//                prev.next=x.next;
//                x.next=null;
                /**
                 * 写法2
                 */
                prev.next=prev.next.next;
//一句话就删掉了,再加上prev.next.next=null就会异常;
//       错:        prev.next.next=null;
                size--;
            }else {
                //prev移动一定要放在else里
                //因为如果有多个val要都删完才能走prev
                prev = prev.next;
            }
        }
    }

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值