顺序表和链表


一、线性表

线性表:数据存储时,按照逻辑连续存储,成线性结构(特点:都有索引概念,索引较小的元素一定逻辑排在索引较大的元素之前

线性表子集:顺序表,链表,栈,队列,字符串

线性表存储分为两种结构:
基于数组的线性表:顺序表(元素不仅逻辑连续,物理上也连续)
基于链表的线性表:值是元素之间得到逻辑连续

二、顺序表

java中的基本数组问题:数组长度固定,声明后只能存放固定长度的数值
顺序表:基于数组的线性表——动态数组(根据数据的大小动态调整)

package seqlist;
//基于数组的顺序表
public class MyArray {
    //存储元素还在数组中
    private  int[] data;
    //当前动态数组中实际存储的元素个数
    private  int size;
    //data.length-此时数组最多存储元素个数,size-实际用的空间

    //默认开辟数字大小为10
    public MyArray(){
        data = new int[10];
    }
    //用户想要传入的数组大小
    public MyArray(int capacity){
        data = new int[capacity];
    }
}

CURD四大操作:增删查改

1.增加:

addFirst(int val):在数组头部插入
addLast(int val):在数组尾部插入
addIndex(int index, int val){}:在数组中间插入

①.打印

//打印当前数组内容
    public String toString(){
        String ret = "[";
        //遍历data数组
        for (int i = 0; i < size; i++) {
            //任何数和String型相加自动变为String型
            ret+=data[i];
            if(i!=size-1) {
                ret +=",";
            }
        }
        ret+="]";
        return ret;
    }

②.扩容及尾插

添加就要考虑原数组是否已满,若size==data.length说明已满,此时应该扩容

    /**
     * 在数组的尾部插入
     * @param value 待插入的新元素值
     */
    public void addLast(int value){
        //先判断当前数组是否已满
        if (size== data.length){
            //当前数组已满
            //数组要扩容
            grow();
        }
        data[size]=value;
        size++;
    }
    private void grow(){
        //原先数组为data然后扩容为原来大小的两倍data.length<<1,返回一个扩容后新数组
        int[] newData=Arrays.copyOf(this.data,this.data.length<<1);
        //指向扩容后新数组
        this.data=newData;
    }

在这里插入图片描述

③.头插

    /**
     *  在数组头部插入
     * @param value 待插入的新元素值
     */
    public void addFirst(int value){
        if(size== data.length){
            grow();
        }
        //在数组头部插入
        //先将原先数组从最后一个元素开始依次向后移动一个单位
        for (int size-1 = 0; i>=0 ; i--) {
             data[i+1]=data[i];
        }
        //此时data[0]就空出来了
        data[0]=value;
        size++;
    }

在这里插入图片描述

④.索引插入

/**
     * 在数组任意位置插入
     * @param index 传入的索引值
     * @param value 要插入的新元素
     */
    public void addIndex(int index ,int value){
        //index<0//index>size,size表示当前有效数组保证连续性,判断index的合法性
        if(index<0||index>size){
            System.err.println("add inedx illegal!");
            return;
        }
        //判断数组是否满
        if(size== data.length){
            grow();
        }
        if (index == 0) {
            addFirst(value);
            return;
        }
        if (index == size) {
            addLast(value);
            return;
        }
        else {
            //将index位置空出来
            for (int i = size-1; i >=index ; i--) {
                data[i+1]=data[i];
            }
            data[index]=value;
            size++;
        }
    }

⑤.编写测试代码及结果

public class Test {
    public static void main(String[] args) {
        MyArray myArray = new MyArray(3);
        myArray.addLast(1);
        myArray.addLast(3);
        myArray.addLast(5);
        myArray.addLast(7);
        System.out.println(myArray);
        myArray.addFirst(10);
        System.out.println(myArray);
        myArray.addIndex(1,22);
        myArray.addIndex(0,33);
        myArray.addIndex(7,44);
        myArray.addIndex(10,55);
        System.out.println(myArray);
    }
}

在这里插入图片描述

2.查找

boolean contains(int value):查看当前数组中是否存在
int get (int index):根据索引取得相应位置
int getByValue(int value):查找当前数组中元素value对应的下标index

①.int getByValue(int value)

/**
     * 在数组中查找value值对应的索引下标
     * @param value
     * @return
     */
    public int getByValue(int value){
        //遍历数组
        for (int i = 0; i <size ; i++) {
            if(data[i]==value){
                return i;
            }
        }
        //此时循环走完还没找到
        return -1;
    }

②.boolean contains(int value)

/**
     * 查看是否存在value
     * @param value
     * @return
     */
    public  boolean contains(int value){
        int index=getByValue(value);
        if(index==-1){
            return false;
        }
        return true;
    }

③.int get (int index)

/**
     * 根据索引查询元素
     * @param  index 索引值
     * @return
     */
    public int get(int index){
        //判断合法性
        if(index<0||index>=size){
            System.err.println("get index illegal!");
            return -1;
        }
        return data[index];
    }

④.测试代码及结果

        System.out.println(myArray);
        System.out.println(myArray.contains(7));
        System.out.println(myArray.getByValue(22));
        System.out.println(myArray.get(3));

在这里插入图片描述

3.改

根据索引修改原先元素
int set (int index,int newValue):将指定索引位置元素修改为newValue,返回修改前元素值

①.int set (int index,int newValue)

 /**
     * 将指定索引位置元素修改为newValue,返回修改前元素值
     * @param index
     * @param newValue
     * @return
     */
    public int set(int index,int newValue){
        //判断合法性
        if(index<0||index>=size) {
            System.err.println("get index illegal!");
            return -1;
        }else{
            int oldValue=data[index];
            data[index]=newValue;
            return oldValue;
        }
    }

②.测试代码及结果

        System.out.println(myArray);
        //[33,10,22,1,3,5,7,44]
        System.out.println(myArray.set(1,100));
        System.out.println(myArray);

在这里插入图片描述

4.删除

 void removeFirst():删除头元素
 void removeLast():删除尾元素
 void removeIndex(int index):根据索引index删除元素
 void removeValueOnce(int value):删除数组中第一个元素值为value的元素
 void removeValueAll(int value):删除数组中所有值为value的元素

①.删除指定位置元素

/**
     * 删除指定索引位置的元素
     * @param index
     */
    public  void removeIndex(int index){
        if(index<0||index>=size) {
            System.err.println("remove index illegal!");
            return;
        }
       //为保证data[i+1]仍然不越界,判断条件为i<size-1
        for (int i = index; i <size-1 ; i++) {
            data[i]=data[i+1];
        }
        size--;
        //删除原先数组的最后一个位置元素
        data[size]=0;
    }

②.删除头元素


    public void removeFirst(){
        removeIndex(0);
    }

③.删除尾元素

   public void removeLast(){
        removeIndex(size-1);
    }

④.删除出现一次值为value的元素

   public void removeValueOnce(int value){
        for (int i = 0; i <size ; i++) {
            if(value==data[i]){
                //此时i对应的索引是第一个值为value的元素
                removeIndex(i);
                return;
            }
        }

    }

⑤.删除所有值为value的元素

public void removeValueAll(in value){
        for (int i = 0; i <size; i++) {
            //重复删除元素时使用while
            //i!=size极端情况后面的全部及当前元素全部删除
            while(value==data[i]&&i!=size){
                //此时i对应的索引是第一个值为value的元素
                removeIndex(i);
                return;
            }
        }
    }

⑥.测试代码及结果

myArray.removeFirst();
        myArray.removeLast();
        myArray.removeIndex(1);
        System.out.println(myArray);

在这里插入图片描述

总结

1.MyArray-包装了一下数组,使其具备可以动态扩容的功能
2.当使用println方法进行一个对象的输出时,需要在该对象所在的类中实现toString(),将一个对象->String
3.成员变量初始化:构造方法
4.动态数组:①缺点:头部删除和添加O(N),扩容:O(N)扩容是一个非常耗时的操作,空间复杂度:O(N) ②优点:根据索引查找元素O(N)
5.完整代码

package seqlist;

import com.sun.media.sound.RIFFInvalidDataException;

import java.util.Arrays;

//基于数组的顺序表
public class MyArray {
    //存储元素还在数组中
    private  int[] data;
    //当前动态数组中实际存储的元素个数
    private  int size;
    //data.length-此时数组最多存储元素个数,size-实际用的空间

    //默认开辟数字大小为10
    public MyArray(){
        data = new int[10];
    }
    //用户想要传入的数组大小
    public MyArray(int capacity){
        data = new int[capacity];
    }

    /**
     * 在数组的尾部插入
     * @param value 待插入的新元素值
     */
    public void addLast(int value){
        //先判断当前数组是否已满
        if (size== data.length){
            //当前数组已满
            //数组要扩容
            grow();
        }
        data[size]=value;
        size++;
    }

    /**
     *  在数组头部插入
     * @param value 待插入的新元素值
     */
    public void addFirst(int value){
        if(size== data.length){
            grow();
        }
        //在数组头部插入
        //先将原先数组从最后一个元素开始依次向后移动一个单位
        for (int i=size-1; i>=0; i--) {
             data[i+1]=data[i];
        }
        //此时data[0]就空出来了
        data[0]=value;
        size++;
    }

    /**
     * 在数组任意位置插入
     * @param index 传入的索引值
     * @param value 要插入的新元素
     */
    public void addIndex(int index ,int value){
        //判断数组是否满
        if(size== data.length){
            grow();
        }
        //index<0//index>size,size表示当前有效数组保证连续性,判断index的合法性
        if(index<0||index>size){
            System.err.println("add inedx illegal!");
            return;
        }
        if (index == 0) {
            addFirst(value);
            return;
        }
        if (index == size) {
            addLast(value);
            return;
        }
        else {
            //将index位置空出来
            for (int i = size-1; i >=index ; i--) {
                data[i+1]=data[i];
            }
            data[index]=value;
            size++;
        }
    }

    //打印当前数组内容
    public String toString(){
        String ret = "[";
        //遍历data数组
        for (int i = 0; i < size; i++) {
            //任何数和String型相加自动变为String型
            ret += data[i];
            if(i!=size-1) {
                ret +=",";
            }
        }
        ret+="]";
        return ret;
    }

    private void grow(){
        //原先数组为data然后扩容为原来大小的两倍data.length<<1,返回一个扩容后新数组
        int[] newData=Arrays.copyOf(this.data,this.data.length<<1);
        //指向扩容后新数组
        this.data=newData;
    }

    /**
     * 在数组中查找value值对应的索引下标
     * @param value
     * @return
     */
    public int getByValue(int value){
        //遍历数组
        for (int i = 0; i <size ; i++) {
            if(data[i]==value){
                return i;
            }
        }
        //此时循环走完还没找到
        return -1;
    }

    /**
     * 查看是否存在value
     * @param value
     * @return
     */
    public  boolean contains(int value){
        int index=getByValue(value);
        if(index==-1){
            return false;
        }
        return true;
    }

    /**
     * 根据索引查询元素
     * @param  index 索引值
     * @return
     */
    public int get(int index){
        //判断合法性
        if(index<0||index>=size){
            System.err.println("get index illegal!");
            return -1;
        }
        return data[index];
    }

    /**
     * 将指定索引位置元素修改为newValue,返回修改前元素值
     * @param index
     * @param newValue
     * @return
     */

    public int set(int index,int newValue){
        //判断合法性
        if(index<0||index>=size) {
            System.err.println("get index illegal!");
            return -1;
        }else{
            int oldValue=data[index];
            data[index]=newValue;
            return oldValue;
        }
    }


    /**
     * 删除指定索引位置的元素
     * @param index
     */
    public  void removeIndex(int index){
        if(index<0||index>=size) {
            System.err.println("remove index illegal!");
            return;
        }
        //为保证data[i+1]仍然不越界,判断条件为i<size-1
        for (int i = index; i <size-1 ; i++) {
            data[i]=data[i+1];
        }
        size--;
        //删除原先数组的最后一个位置元素
        data[size]=0;
    }

    public void removeFirst(){
        removeIndex(0);
    }

    public void removeLast(){
        removeIndex(size-1);
    }

    public void removeValueOnce(int value){
        for (int i = 0; i <size ; i++) {
            if(value==data[i]){
                //此时i对应的索引是第一个值为value的元素
                removeIndex(i);
                return;
            }
        }

    }

    public void removeValueAll(int value){
        for (int i = 0; i <size; i++) {
            //重复删除元素时使用while
            //i!=size极端情况后面的全部及当前元素全部删除
            while((value==data[i]) && (i!=size)){
                //此时i对应的索引是第一个值为value的元素
                removeIndex(i);
                return;
            }
        }
    }
}

package seqlist;

public class Test {
    public static void main(String[] args) {
        MyArray myArray = new MyArray(3);
        myArray.addLast(1);
        myArray.addLast(3);
        myArray.addLast(5);
        myArray.addLast(7);
        System.out.println(myArray);
        myArray.addFirst(10);
        System.out.println(myArray);
        myArray.addIndex(1,22);
        myArray.addIndex(0,33);
        myArray.addIndex(7,44);
        System.out.println(myArray);
        //[33,10,22,1,3,5,7,44]

//        System.out.println(myArray.contains(7));
//        //2
//        System.out.println(myArray.getByValue(22));
//        //1
//        System.out.println(myArray.get(3));

//        System.out.println(myArray.contains(7));
//        System.out.println(myArray.getByValue(22));
//        System.out.println(myArray.get(3));

        myArray.removeFirst();
        myArray.removeLast();
        myArray.removeIndex(1);
        System.out.println(myArray);
    }
}

链表

链表:逻辑上连续,多个节点采用挂载的方式进行链接,物理上不连续。类比:火车
火车这种结构:都是从头开始遍历,走到火车尾

车厢:具体存储元素的类

class Node{
  int data;//具体存储数据
  Node next;//存储下一节车厢的地址
  }

火车:就是尤一系列车厢拼起来
单列表:只能从头部开始遍历,依次走到尾部,单项遍历

//单链表-火车类
class SingList{
  int size;//车厢个数
  Node head;//第一节车厢的地址(头节点)
}

1.增加:

①.火车类和车厢类

package seqlist;

/**
 * 火车类,拼接是由多个车厢拼接在一起
 */
public class SingleLinkedList {
    //当前火车中车厢的节点个数(实际就是具体元素的个数)
    private  int size;
    //当前火车的火车头
    private Node head;
}

/**
 * 火车的车厢类,一个车厢只能保存一个元素
 */
class Node{
    //存储具体数据
    int val;
    //保存下一个车厢的地址
    Node next;
    public  Node (int val){
        this.val=val;
    }
}

②.头插法

 /**
     * 在火车头部添加元素-添加一个车厢的节点
     * @param val
     */
    public  void addFirst(int val){
        //新建一个车厢节点
        Node node = new Node(val);
        //判断当前的火车是否为空
        if(head==null){
            head =node;
        }else {
            //火车中有节点,要把当前新车厢挂载到火车头部
            node.next=head;
            head=node;
        }
        size++;
    }

在这里插入图片描述

③.toString方法

    public String toString(){
        String ret="";
        //遍历火车这个类
        //从火车头(head)走到火车尾部()
        //暂时存储当前头节点地址
        Node node =head;
        while(node!=null){
            ret+=node.val;
            ret+="->";
            //继续访问下一节点;
            node=node.next;
        }
        //表示当前走到尾
        ret+="NULL";
        return ret;
    }

④.任意位置插入

/**
     * 在单列表的任意一个索引位置插入元素val
     * @param index
     * @param val
     */
    public void addIndex(int index,int val){
        //1.合法性
        if (index<0|index>size){
            System.err.println("add index illegal!");
            return ;
        }
        //头插法
        if (index==0){
            addFirst(val);
            return;
        }
        //2.插入元素
        Node node = new Node(val);
        //需要找到待插入的前去
        Node prev = head;
        for (int i = 0; i < index-1; i++) {
            prev=prev.next;
        }
        //此时prev指向待插入位置的前驱节点
        node.next=prev.next;
        prev.next=node;
        size++;
    }

⑤.尾插法

    /**
     * 在单列表的尾部插入元素
     * @param index
     * @param val
     */
    public void addLast(int val){
        addIndex(size,val);
    }

    //测试代码
        SingleLinkedList singleLinkedList=new SingleLinkedList();
        singleLinkedList.addLast(1);
        singleLinkedList.addLast(2);
        singleLinkedList.addLast(3);
        singleLinkedList.addIndex(1,10);
        //1,10,2,3->NULL
        System.out.println(singleLinkedList);

2.查找:

get(int index):返回index位置的元素值//合法性,index<0||index>=size
contains(int value):查询值为value的元素是否在单链表中存在

①.判断合法性

    /**
     * 判断用户输入的index是否合法(改,查,删除使用)
     * @param index
     * @return
     */
    private boolean rangeCheck(int index){
        if (index < 0||index>=size) {
            return false;
        }
        return true;
    }

②.get(int index)方法

 public int get(int index){
        if (rangeCheck(index)){
            //index合法
            //从头节点开始遍历链表,走到index位置
            Node node=head;
            //规定了走的步数
            for (int i = 0; i < index; i++) {
                node =node.next;
            }
            return node.val;
        }else{
            System.err.println("get index illegal!");
            return -1;
        }
       }

②.contains(int value)方法

 /**
     * 判断当前链表中是否有包含值为val的节点
     * @param val
     * @return
     */
    public boolean contains(int val){
        for (Node temp= head; temp!=null ; temp=temp.next) {
            if(temp.val==val){
                return true;
            }
        }
        return false;
    }

3.改:

set(int index,int newValue):修改index位置的值为newValue//合法性index<0||index>=size

①.set(int index,int newValue)方法

  /**
     * 将单链表索引为index的节点值改为newVal
     * @param index
     * @param newVal
     * @return
     */
    public int set(int index,int newVal){
        if (rangeCheck(index)) {
            Node node=head;
            for (int i = 0; i <index ; i++) {
                node=node.next;
            }
            int oldVal= node.val;
            node.val=newVal;
            return oldVal;
        }else{
            System.err.println("set index illegal!");
            return -1;
        }
    }

②.测试代码

  SingleLinkedList singleLinkedList=new SingleLinkedList();
        singleLinkedList.addLast(1);
        singleLinkedList.addLast(2);
        singleLinkedList.addLast(3);
        singleLinkedList.addIndex(1,10);
        //1,10,2,3->NULL
        System.out.println(singleLinkedList);
        //2
        System.out.println(singleLinkedList.get(2));
        //false
        System.out.println(singleLinkedList.contains(100));
        singleLinkedList.set(2,200); 
        System.out.println(singleLinkedList);

4.删除:

removeIndex(int index)//删除index节点
removeValueOnce(int value);//删除单链表中第一个值为value的节点
removeValueAll(int value);//删除单链表中所有值为value的节点

在单链表的插入余删除中都需要找到前驱节点,只有头节点没有前驱节点,因此需要特殊处理

①.removeIndex(int index)代码

public void removeIndex(int index){
        //合法性
    if(rangeCheck(index)) {
        if (index == 0) {
            //边界 删除头节点的情况
            Node temp = head;
            head = head.next;
            temp.next = null;
            size--;
        } else {
            //index中间位置
            //找到前驱节点
            Node prev = head;
            for (int i = 0; i < index - 1; i++) {
                prev = prev.next;
            }
            //待删除节点
            Node cur = prev.next;
            prev.next = cur.next;
            cur.next = null;
            size--;
        }
    }else{
        System.err.println("remove index illegal!");
    }
}

public void removeFirst(){
        removeIndex(0);
}

public  void removeLast(){
        removeIndex(size-1);
}

②.removeValueOnce(int value)代码

 /**
     * 删除链表中第一次出现的待删除元素
     * @param val
     */
    public void removeValueOnce(int val){
        //遍历链表,找到值为val的节点
        //找到删除节点(正常删除都要找前驱,只有头节点没有前驱)
        if(head.val==val){
            //头结点是待删除结点
            Node temp=head;
            head=head.next;
            temp.next=null;
            size--;
        }else{
            //此时head一定不是待删除节点
            Node prev=head;
            //判断前驱的下一个节点是否等于val
            //看你取值用的是哪一个引用,就判断哪个引用不为空
            while(prev.next!=null) {//存在空指针问题
                if (prev.next.val == val) {
                    Node cur=prev.next;
                    prev.next=cur.next;
                    cur.next=null;
                    size--;
                    return;
                }
                prev=prev.next;
            }
        }
    }

③.removeValueAll(int value)代码

 public void removeIndexAll(int val){
        while(head!=null&&head.val==val){
            head=head.next;
            size--;
        }
        if(head==null){
            //此时链表中的值全是val
            return ;
        }else{
            //此时head一定不是待删除节点,链表中还有节点
            Node prev=head;
            while(prev.next!=null){
                if (prev.next.val == val) {
                   Node cur=prev.next;
                   prev.next=cur.next;
                   cur.next=null;
                   size--;
                }else{
                    //只有确保prev.next不是待删除节点才能移动prev指向
                    //prev一定不是待删除节点
                    prev=prev.next;
                }
            }
        }
    }

4.完整代码:

package seqlist;

import java.rmi.ServerError;

/**
 * 火车类,拼接是由多个车厢拼接在一起
 */
public class SingleLinkedList {
    //当前火车中车厢的节点个数(实际就是具体元素的个数)
    private  int size;
    //当前火车的火车头
    private Node head;

    /**
     * 在火车头部添加元素-添加一个车厢的节点
     * @param val
     */
    public  void addFirst(int val){
        //新建一个车厢节点
        Node node = new Node(val);
        //判断当前的火车是否为空
        if(head == null){
            head =node;
        }else {
            //火车中有节点,要把当前新车厢挂载到火车头部
            node.next=head;
            head=node;
        }
        size++;
    }

    /**
     * 在单列表的任意一个索引位置插入元素val
     * @param index
     * @param val
     */
    public void addIndex(int index,int val){
        //1.合法性
        if (index<0|index>size){
            System.err.println("add index illegal!");
            return ;
        }
        //头插法
        if (index==0){
            addFirst(val);
            return;
        }
        //2.插入元素
        Node node = new Node(val);
        //需要找到待插入的前去
        Node prev = head;
        for (int i = 0; i < index-1; i++) {
            prev=prev.next;
        }
        //此时prev指向待插入位置的前驱节点
        node.next=prev.next;
        prev.next=node;
        size++;
    }

    /**
     * 在单列表的尾部插入元素
     * @param in dex
     * @param val
     */
    public void addLast(int val){
        addIndex(size,val);
    }



    public String toString(){
        String ret="";
        //遍历火车这个类
        //从火车头(head)走到火车尾部()
        //暂时存储当前头节点地址
        Node node =head;
        while(node!=null){
            ret+=node.val;
            ret+="->";
            //继续访问下一节点;
            node=node.next;
        }
        //表示当前走到尾
        ret+="NULL";
        return ret;
    }

    /**
     * 判断用户输入的index是否合法(改,查,删除使用)
     * @param index
     * @return
     */
    private boolean rangeCheck(int index){
        if (index < 0||index>=0) {
            return false;
        }
        return true;
    }

    public int get(int index){
        if (rangeCheck(index)){
            //index合法
            //从头节点开始遍历链表,走到index位置
            Node node=head;
            //规定了走的步数
            for (int i = 0; i < index; i++) {
                node =node.next;
            }
            return node.val;
        }else{
            System.err.println("get index illegal!");
            return -1;
        }
    }

    /**
     * 判断当前链表中是否有包含值为val的节点
     * @param val
     * @return
     */
    public boolean contains(int val){
        for (Node temp= head; temp!=null ; temp=temp.next) {
            if(temp.val==val){
                return true;
            }
        }
        return false;
    }

    /**
     * 将单链表索引为index的节点值改为newVal
     * @param index
     * @param newVal
     * @return
     */
    public int set(int index,int newVal){
        if (rangeCheck(index)) {
            Node node=head;
            for (int i = 0; i <index ; i++) {
                node=node.next;
            }
            int oldVal= node.val;
            node.val=newVal;
            return oldVal;
        }else{
            System.err.println("set index illegal!");
            return -1;
        }
    }



}



/**
 * 火车的车厢类,一个车厢只能保存一个元素
 */
class Node{
    //存储具体数据
    int val;
    //保存下一个车厢的地址
    Node next;

    public  Node (int val){
        this.val=val;
    }
}
package seqlist;

public class Test {
    public static void main(String[] args) {
//        MyArray myArray = new MyArray(3);
//        myArray.addLast(1);
//        myArray.addLast(3);
//        myArray.addLast(5);
//        myArray.addLast(7);
//        System.out.println(myArray);
//        myArray.addFirst(10);
//        System.out.println(myArray);
//        myArray.addIndex(1,22);
//        myArray.addIndex(0,33);
//        myArray.addIndex(7,44);
//        System.out.println(myArray);
//        //[33,10,22,1,3,5,7,44]

//        System.out.println(myArray.contains(7));
//        //2
//        System.out.println(myArray.getByValue(22));
//        //1
//        System.out.println(myArray.get(3));

//        System.out.println(myArray.contains(7));
//        System.out.println(myArray.getByValue(22));
//        System.out.println(myArray.get(3));

//        myArray.removeFirst();
//        myArray.removeLast();
//        myArray.removeIndex(1);
//        System.out.println(myArray);


//        使用者的是火车类
//        SingleLinkedList singleLinkedList = new SingleLinkedList();
//        singleLinkedList.addFirst(1);
//        singleLinkedList.addFirst(3);
//        singleLinkedList.addFirst(5);
//        System.out.println(singleLinkedList);

        SingleLinkedList singleLinkedList=new SingleLinkedList();
        singleLinkedList.addLast(1);
        singleLinkedList.addLast(2);
        singleLinkedList.addLast(3);
        singleLinkedList.addIndex(1,10);
        //1,10,2,3->NULL
        System.out.println(singleLinkedList);
        //2
        System.out.println(singleLinkedList.get(2));
        //false
        System.out.println(singleLinkedList.contains(100));
        singleLinkedList.set(2,200);
        System.out.println(singleLinkedList);


    }
 }

三、练习题

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

方法一:常规解法

package leetcode;

/**
 * LeetCode第203号问题-
 * 删除链表中所有Node.val == val节点,并返回新的头节点
 */
public class Num203 {
    public ListNode removeElements(ListNode head, int val) {
        //头节点就是待删除节点
        while(head!=null&&head.val==val){
            head=head.next;
        }
        if (head == null) {
            return null;
        }else{
            //头节点一定不是待删除结点且链表不为空
            ListNode prev=head;
            while(prev.next!=null){
                if(prev.next.val==val){
                    ListNode cur=prev.next;
                    prev.next=cur.next;
                }else{
                    //只有当prev.next.val!=val
                    prev=prev.next;
                }
            }
        }
        return head;
    }
}

方法二:利用递归方法

  //递归方法求解
  public class Num203 {
    public ListNode removeElements(ListNode head, int val) {
        if(head==null){
            return null;
        }
        //将haed.next以及之后的节点处理,交给removeElements(head.next,val)
        head.next=removeElements(head.next,val);
        //自己处理下一个头节点
        if (head.val == val) {
            return head.next;
        }
        return head;
    }
}

本地自测代码:
1.在本地新建一个build方法,创建一个和刚出错测试链表完全一致的链表
2.在本地传入测试链表,单步调试


/**
 * LeetCode第203号问题-
 * 删除链表中所有Node.val == val节点,并返回新的头节点
 */
public class Num203 {
    public static void main(String[] args){
        ListNode head=build();
        Num203 num203=new Num203();
        ListNode newHead =num203.removeElements(head,6);
        System.out.println(newHead);
    }
    //创建一个链表
    public  static ListNode build(){
        ListNode node1=new ListNode(1);
        ListNode node2=new ListNode(2);
        ListNode node3=new ListNode(6);
        ListNode node4=new ListNode(3);
        ListNode node5=new ListNode(4);
        ListNode node6=new ListNode(5);
        ListNode node7=new ListNode(6);
        node1.next=node2;
        node2.next=node3;
        node3.next=node4;
        node4.next=node5;
        node5.next=node6;
        node6.next=node7;
        return node1;
    }
    public ListNode removeElements(ListNode head, int val) {
        //方法一:
        //头节点就是待删除节点
        while (head != null && head.val == val) {
            head = head.next;
        }
        if (head == null) {
            return null;
        } else {
            //头节点一定不是待删除结点且链表不为空
            ListNode prev = head;
            while (prev.next != null) {
                if (prev.next.val == val) {
                    ListNode cur = prev.next;
                    prev.next = cur.next;
                } else {
                    //只有当prev.next.val!=val
                    prev = prev.next;
                }
            }
        }
        return head;



//        方法二
//        if(head==null){
//            return null;
//        }
//        //将haed.next以及之后的节点处理,交给removeElements(head.next,val)
//        head.next=removeElements(head.next,val);
//        //自己处理下一个头节点
//        if (head.val == val) {
//            return head.next;
//        }
//        return head;
    }
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值