【Java21】堆栈和队列,数组和链表,红黑树,List子接口/ArrayList/LinkedList,set子接口


1.堆栈和队列

数据结构:计算机组织管理数据的方式。堆栈指的是内存图中的,不是堆。
在这里插入图片描述

2.数组和链表

在这里插入图片描述
如下查询慢:知道张三在哪,不能马上知道王五在哪,挨个查。如下增删虽然不用整个动(如删除李四,只需要将箭头指向王五就行),但是还是要先查找到再删除,效率还是慢。但是直接删除张三或马六头尾元素快。
在这里插入图片描述

3.红黑树

二叉树:每个节点最多两个子节点。查找树:左小右大(二分法)。平衡树:左右尽量相等(一边的节点层次不会超过另一边的两倍)。二查平1倍:红黑树(数组和链表折中方案)。

二叉搜索树BST(二查):插入或查询一节点时,树的每一行只需要和这一行的一个节点比较(因为左小右大),复杂度完全依赖树的深度。树的行数即高度=logn【n为节点总数,2的树行数次方为n】,BST读和写的复杂度都为logn。

有序数组查找时用二分查找法,时间复杂度logn。有序数组查询最差情况logn,而当BST为单边时(最差情况),BST查询和插入都为o(n)。

问题:为什么很多情况下用BST,而不是有序数组二分查找?因为有序数组查找用二分查找logn,但是插入要移动,插入时间复杂度为o(n)。
在这里插入图片描述
BST很少在语言内部数据结构存储里用(因为下面直线情况),自平衡二叉树AVL(二查平)BST(二查)的继承优化:左子树和右子树都是平衡二叉树,而且左子树和右子树深度之差绝对值不会超过1(左旋和右旋),AVL 读和写的复杂度最差情况都为O(logn)。
在这里插入图片描述
AVL平衡左右子树相差1,这个条件很苛刻,导致很多情况下都不满足这个平衡条件,需要旋转变换,变换的话需要浪费时间。红黑树(二平查1倍)平衡条件更加宽松些左右深度差一倍【如下节点数相同是上界,节点数差一倍是下界(因为红节点子节点必须为黑)】,这样宽松条件导致我们在插入节点时候变化更少的,所以红黑树写的性能会高一些。
在这里插入图片描述
红黑树整体复杂度也是O(logn),树的搜索或插入复杂度完全依赖于树的深度,为什么深度差一倍还是O(logn)?如下左边3是3层,右边红黑树。
在这里插入图片描述
如下是红黑树的插入变色流程,最上面根节点必须为黑,插入节点为红节点(看插入节点的父节点和父节点的兄弟节点即叔节点)。null算叶子节点即黑节点。当前插入的003是爷爷节点的右右。
在这里插入图片描述
如下左旋+变色
在这里插入图片描述
在这里插入图片描述

4.List子接口

如下是集合的框架图
在这里插入图片描述
在这里插入图片描述

package com.itheima01.list;
import java.util.ArrayList;
import java.util.List;
/*
    Collection子接口:List
	1. List的特点:重索序
		1. 有先后顺序:元素存储的顺序和取出的顺序相同
		2. 具有整数索引,就是下标
		3. 允许重复元素
	 
	2. List的方法(带索引)(List特有的,共有的在Collection讲过)
		1. add(int index, E element) :往索引位置添加一个元素
			1. Java中的 三个越界异常
			 	1. IndexOutOfBoundsException  集合
			 	2. ArrayIndexOutOfBoundsException  数组
			 	3. StringIndexOutOfBoundsException 字符串越界
		2. get(int index):获取指定索引的元素
		3. remove(int index):移除指定索引的元素
		4. set(int index, E element) :修改指定索引的元素值
*/
public class ListDemo {
    
    
    public static void main(String[] args) {
    
    
//        add();
        List<String> list = new ArrayList<>();
        list.add("周楠");
        list.add("王凤枝");
        list.add("王凯");
        String s = list.get(2);
        System.out.println(s); //王凯
        
        list.remove(2);
        System.out.println(list); //[周楠, 王凤枝]
        
        list.set(1,"昌老师");
        System.out.println(list); //[周楠, 昌老师]
    }

//11111111111111111111111111111111111111111111111111111111111111111111111111111
    private static void add() {
    
    
        List<String> list = new ArrayList<>();
        list.add("周楠");
        list.add("王凤枝");
        list.add("王凯");
        /*
            add(int index, element)
                往指定索引位添加元素
                index = list.size()
                IndexOutOfBoundsException: : 索引越界异常
        */
        list.add(3,"田锁"); //不越界,4越界
        System.out.println(list);

        String[] array = {
    
    };
 //System.out.println(array[0]); //ArrayIndexOutOfBoundsException : 数组索引越界

        String str = "abc";  // 字符串底层也是数组
 // char c = str.charAt(3); //索引0,1,2 
// System.out.println(c);  //StringIndexOutOfBoundsException:字符串索引越界
    }
}

5.ArrayList的扩容原理

Stringbuild默认length=16,扩容2倍。ArrayList底层是存Object数组,新建一个长度为原来1.5倍新数组(空)。
在这里插入图片描述
如下10进制的4就是2进制的0100(8421),3/2=1,ArrayList.java源码中出现左右移。
在这里插入图片描述

package com.itheima01.list;
import java.util.ArrayList;
/*
*   ArrayList: 数组
*       1. 最常用: 适合 查询需求比较多的场景
*       2. 原理: ArrayList扩容原理
*               ArrayList底层是数组,数组长度不可变,为什么ArrayList又可变呢? 因为数据迁移
*/
public class ArrayListDemo {
    
    
    public static void main(String[] args) {
    
    
        ArrayList<String> list = new ArrayList<>();
        list.add("xx");
        System.out.println(3 >> 1); // 1 //除2取整
        System.out.println(4 >> 1); // 2
        System.out.println(10 >> 1); // 5
        System.out.println(3 << 2); //12 //3*2*2,左移2位
    }
}

6.LinkedList

package com.itheima01.list;
import java.util.LinkedList;
/*
    LinkedList特点
		1. 底层数据结构: 双向链表
		2. 查询速度慢,增删快(增删需求多而且增删首尾用LinkedList)
 		3. 特有方法(不能使用多态,父类不能调子类特有方法)
 			1. addFirst 元素添加在链表开头
	 		2. addLast(add相同) 元素添加在链表结尾
	 		3. getFirst 获取链表开头
	 		4. getLast  获取链表结尾
	 		5. removeFirst 移除并返回链表开头
	 	    6. removeLast 移除并返回链表结尾
            //下面两个不需要掌握
	 	    7. pop 从此列表所表示的堆栈处弹出一个元素(最顶部元素弹出,removeFirst)
	 		8. push 将元素推入此列表所表示的堆栈(元素存储到集合顶部,addFirst)
*/
public class LinkedListDemo {
    
    
    public static void main(String[] args) {
    
    
//        method01();
        LinkedList<String> list = new LinkedList<>();
        list.add("张三"); // 是链表,不是按堆栈结构添加元素
        list.add("李四");
        list.add("王五");
        
        // 链表 -> 堆栈 ,张三在栈顶
//        String pop = list.pop(); // 弹栈: 栈顶元素()
//        String removeFirst = list.removeFirst();//效果同上
//        System.out.println(pop);
        list.push("王二"); //栈顶添加,效果等同于add
        System.out.println(list);
    }

    private static void method01() {
    
    
        LinkedList<String> list = new LinkedList<>();
        list.add("张三");
        list.add("李四");
        list.add("王五");
        list.addFirst("王二");
        list.addLast("马六");
        System.out.println(list);
        
        String first = list.getFirst();
        String last = list.getLast();
        System.out.println(first + ","  + last);
        System.out.println(list);
        
        list.removeFirst();
        list.removeLast();
        System.out.println(list);
    }
}

7.set子接口

package com.itheima02.set;
import java.util.HashSet;
import java.util.Set;

public class SetDemo {
    
    
    public static void main(String[] args) {
    
    
        Set<String> set = new HashSet<>();
        set.add("张三");
        set.add("李四");
        boolean result = set.add("王五");
        System.out.println(result); //true 
        
        boolean result2 = set.add("王五");
        System.out.println(result2); //false //元素不可重复
        System.out.println(set);//[李四,张三,王五] //存取不保证顺序
    }
}

B站/知乎/微信公众号:码农编程录
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43435675/article/details/107384494