#数据结构-链表

数据结构:描述和组织数据的一种方式

1.顺序表

物理上(内存)和逻辑上都是连续的
对于顺序表来说:增删改查
增/删:移动数据时间复杂度 O(n)
查找/修改:给定一个下标进行查找 O(1)
适合经常进行查找或者修改的时候,使用顺序表好一点
频繁的插入和删除 不适合 因为每次都要移动数据
【插入扩容的话会浪费空间】

1. 1打印顺序表
1.2. 在顺序表指定位置新增元素
public class MyArrayList {
    public int[] elem;
    public int usedSize;
    public MyArrayList(){
        this.elem = new int[5];//构造方法,分配大小位5的空间
    }

    //打印顺序表
    public void display(){
        for (int i = 0; i <this.usedSize ; i++) {
            System.out.print(this.elem[i]+" ");
        }
        System.out.println();
    }

    //在pos位置(指定位置)新增元素
    public void add(int pos,int data){
        if(pos < 0 || pos > this.usedSize){
            System.out.println("pos位置不合法!");
            return;
        }
        //如果elem满了,用扩容函数对其进行扩容
        if(this.isFull()){
            System.out.println("扩容了");
            this.elem = Arrays.copyOf(this.elem,2*this.elem.length);

        }


        //挪开函数
        for (int i = this.usedSize-1; i >= pos ; i--) {
            this.elem[i+1] = this.elem[i];
        }
        this.elem[pos] = data;
        this.usedSize++;
    }
    public boolean isFull(){
        if(this.usedSize == this.elem.length){
            return true;
        }
        return false;
    }
}

调用:

  public static void main(String[] args) {
        MyArrayList myArrayList = new MyArrayList();//实例化有了一个顺序表
        myArrayList.add(0,11);
        myArrayList.add(1,12);
        myArrayList.add(2,13);
        myArrayList.add(3,14);
        myArrayList.add(4,15);
        myArrayList.add(5,16);
        myArrayList.display();
    }

结果:
在这里插入图片描述

1.3.判定是否包含某个元素
//3.判定是否包含某个元素
    //首先判断是否为空
    public  boolean isEmpty(){
       return this.usedSize == 0;
        
    }
    public boolean contains(int toFind) {
        if (isEmpty()) {
            System.out.println("顺序表为空!");
            return false;
        }
        for (int i = 0; i < this.usedSize; i++) {
            if (this.elem[i] == toFind) {
                return true;
            }
        }
        return false;
    }
1.4. 查找某个元素对应的位置【下标】
//4.查找某个元素对应的位置【下标】  找不到返回-1
    public int search(int toFind) {
        if (isEmpty()) {
            System.out.println("顺序表为空!");
            return -1;
        }
        for (int i = 0; i < this.usedSize; i++) {
            if (this.elem[i] == toFind) {
                return i;
            }
        }
        return -1;
    }

1.5. 获取pos位置的元素
//5.获取pos位置的元素  pos != usedSize
    public int getPos(int pos) {
       /* if(pos <0 || pos >= usedSize){
            System.out.println("pos位置不合法");
            return -1;//不好的地方是pos可能真是-1
        }
        return this.elem[pos];
    }*/
        if (pos < 0 || pos >= usedSize) {
            throw new ArrayIndexOutOfBoundsException("pos位置不合法");
            //自定义的异常
        }
        return this.elem[pos];
    }
1.6. 获取顺序表有效数据的长度
 //6.获取顺序表有效数据的长度
    public int size(){
        return this.usedSize;
    }
1.7. 给pos位置的元素设为value 更新
//7.给pos位置的元素设为value  更新
    public void setPos(int pos,int value){
        if (pos < 0 || pos >= this.usedSize) {
            throw new ArrayIndexOutOfBoundsException("pos位置不合法!");
        }
        this.elem[pos] = value;
    }
1.8. 删除第一次出现的关键字key
//8.删除第一次出现的关键字key
    public void remove(int toRemove){
        //首先判断是否为空
        //找到要删除的元素的下标
        int index = search(toRemove);
        if (index == -1) {
            System.out.println("没有你要删除的数字"+toRemove);
            return;
        }
        for (int i = index; i < usedSize-1; i++) {
            this.elem[i] = this.elem[i+1];
        }
        this.usedSize--;//有效数据-1
        System.out.println("删除成功了!");
    }
1.9.清空顺序表
 //9.清空顺序表
    public void clear(){
        //this.usedSize = 0;  法一
        //法二
        for (int i = 0; i < this.usedSize; i++) {
            this.elem[i] = 0;//把每一个元素置为0,如果是引用类型的话,要全置为null
        }
        this.usedSize = 0;
    }

2. 链表

逻辑上是连续的,内存(物理)上不一定连续
单链表
双向链表
头结点:

  1. 数据域中不存放数据 / 数据中的数据没有意义
  2. 头结点是不动的
2.1 创建链表 遍历链表
//创建链表
class Node{
    public int val;//默认值0
    public Node next;//默认值NULL

    public Node(int val){
        this.val = val;
    }
}
//创建链表
public class MyLinkedList {
    public Node head;//单链表的头结点的引用
    public void createLinkedList(){
        Node node1 = new Node(12);//node存储的就是节点的地址
        Node node2 = new Node(23);
        Node node3 = new Node(34);
        Node node4 = new Node(45);
        node1.next = node2;//next域存储的是下一个节点的地址
        node2.next = node3;
        node3.next = node4;
        this.head = node1;//头结点
    }
    //遍历链表
    public void show(){
        Node cur = this.head;
        while (cur != null) {
            System.out.print(cur.val+" ");
            cur = cur.next;
        }
        System.out.println();
    }
     //调用
    public static void main(String[] args) {
        MyLinkedList myLinkedList = new MyLinkedList();
        myLinkedList.createLinkedList();
        myLinkedList.show();
    }
}
2.2 头插法
//头插法 插入一个节点时,一定要先绑后面
    public void addFirst(int data){
        Node node = new Node(data);
        node.next = head;
        head = node;
    }
2.3 尾插法
//尾插法
    public void addLast(int data){ 
        Node node = new Node(data);
        if(this.head == null){
            this.head = node;
            return;
        }
        Node cur = this.head;
        //找到尾节点
        while (cur.next != null) {
            cur = cur.next;
        }
        cur.next = node;
    }
2.4 任意位置插入,第一个数据节点为0号下标
 //任意位置插入
    //1.index的合法判断
    //2.两种特殊的情况  0  size
    //3.找到index-1位置的节点  cur
    //4.node.next = cur.next
    //  cur.next = node;
    public boolean addIndex(int index,int data){
        if (index < 0 || index > getSize()) {
            System.out.println("index位置不合法!");
            return false;
        }
        if (index == 0) {
            addFirst(data);
            return true;
        }
        if (index == getSize()) {
            addLast(data);
            return true;
        }
        Node node = new Node(data);
        Node cur = findIndexSubOne(index);
        node.next = cur.next;
        cur.next = node;
        return true;
    }
    private  Node findIndexSubOne(int index){
        Node cur = this.head;
        while (index-1 != 0) {
            cur = cur.next;
            index--;
        }
        return cur;
    }
2.5 删除第一次出现关键字为key的节点
 private Node searchPrev(int key){
        Node cur = this.head;
        while (cur.next != null) {
            if (cur.next.val == key) {
                return cur;
            }
        }
        return null;
    }
public void remove(int key){
        if (this.head.val == key) {
            this.head = this.head.next;
            return;
        }
        Node prev = searchPrev(key);
        if(prev == null){
            System.out.println("没有你要删除的节点!");
            return;
        }
        Node del = prev.next;
        prev.next = del.next;
    }
2.6 删除所有值为key的列表 只遍历单链表一遍
//删除所有值为key的列表  只遍历单链表一遍
    //cur当前需要删除的节点
    //prev当前需要删除的节点的前驱
    public void removeAllKey(int key){
        if (head == null) {
            System.out.println("空!");
            return;

        }
        Node cur = this.head.next;
        Node prev = this.head;
        //从第二个节点开始遍历
        while (cur !=null) {
            if (cur.val == key) {
                prev.next = cur.next;
                cur = cur.next;
            }else{
                prev = cur;
                cur = cur.next;
            }
        }
        //头结点
        if (this.head.val == key) {
            this.head = this.head.next;
        }
    }
    //清空列表
    public void clear(){
        this.head = null;//稍微粗暴
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值