简单常用数据结构

栈(stack)

在这里插入图片描述

栈(stack)是限制插入和删除只能在一个位置上进行的表,该位置是表的末端,叫做栈顶 (top)。它是后进先出(LIFO)的。对栈的基本操作只有 push(进栈)和 pop(出栈)两种, 前者相当于插入,后者相当于删除最后的元素。

队列(queue)

在这里插入图片描述
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的 后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为 队尾,进行删除操作的端称为队头。

链表 (link)

在这里插入图片描述

散列表(Hash Table)

在这里插入图片描述

散列表(Hash table,也叫哈希表)是一种查找算法,散列表算法希望能尽量做到不经过任何比较,通过一次存取就能得到所查找的数据元素。

  • 直接定址法: 取关键字或关键字的某个线性函数值为散列地址。
    即:h(key) = key 或 h(key) = a * key + b,其中 a 和 b 为常数。
  • 数字分析法
  • 平方取值法: 取关键字平方后的中间几位为散列地址。
  • 折叠法:将关键字分割成位数相同的几部分,然后取这几部分的叠加和作为散列地址。
  • 除留余数法:取关键字被某个不大于散列表表长 m 的数 p 除后所得的余数为散列地址, 即:h(key)=keyMODp p≤m
  • 随机数法:选择一个随机函数,取关键字的随机函数值为它的散列地址, 即:h(key) = random(key)

其中除留余数法就是我们Map中使用的逻辑,Map中获取table下标的逻辑是:
hash & (table.length -1) 等价于 hash%table.length ,等价的原因是length是2^n

这种时间查询复杂度在没有冲突的情况下是O(1)

排序二叉树

在这里插入图片描述

首先如果普通二叉树每个节点满足:左子树所有节点值小于它的根节点值,且右子树所有节点值
大于它的根节点值,则这样的二叉树就是排序二叉树。

插入

在这里插入图片描述

删除

在这里插入图片描述

查询

查找操作的主要流程为:先和根节点比较,如果相同就返回,如果小于根节点则到左子树中 递归查找,如果大于根节点则到右子树中递归查找。因此在排序二叉树中可以很容易获取最 大(最右最深子节点)和最小(最左最深子节点)值。

红黑树

我们看到上面的图,二叉树在某些特殊情况下,有可能变成链表。为了解决这个问题,出现了红黑树。

特征

  • 每个节点或者是黑色,或者是红色。
  • 根节点是黑色。
  • 每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL 或 NULL)的叶子节点!]
  • 如果一个节点是红色的,则它的子节点必须是黑色的。
  • 从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。

在这里插入图片描述
细节内容大家可以看别人的文章:
红黑树(一)之 原理和算法详细介绍
红黑树(五)之 Java的实现

B-Tree 和 B+Tree

由于二叉树的树的高度问题,衍生出了B-Tree。关于B树和B+树,看下面的三阶树:
在这里插入图片描述
在这里插入图片描述
对比差异:

  • 都是3阶的B-Tree和B+Tree,B-Tree一个节点只有2个关键字,而B+Tree有3个关键字。
  • B+Tree叶子结点包含了所有信息,而B-Tree叶子结点没有全部信息
  • B+Tree比B-Tree存储的数据更少
  • 在范围查询方面,B+Tree可以直接查询叶子结点,而B-Tree不可以,所以范围查询B+Tree更有优势
  • 对于等值查询,B+Tree查询效率比较平衡,因为最终都要落到叶子结点上,而B-Tree,有可能在根结点就查询到数据。可以直接返回内容,速度更快。

位图

位图的原理就是用一个 bit 来标识一个数字是否存在,采用一个 bit 来存储一个数据,所以这样可 以大大的节省空间

package com.jarvis.java;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author jinzhaopo
 * @date 2024-01-26 15:39
 */
public class BitMap {

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @ToString
    private static class User {

        /**
         * 判断新用户:0 不是,1 是
         */
        private Integer bolNew;

        /**
         * 是否启用:0 不启用,1 启用
         */
        private Integer bolEnable;

        /**
         * 是否超级管理员:0 不是超级管理员 , 1 是超级管理员
         */
        private Integer bolSuper;

        /**
         * 标示数据库存储的值
         */
        private Integer dbData;

        public User(Integer bolNew, Integer bolEnable, Integer bolSuper) {
            this.bolNew = bolNew;
            this.bolEnable = bolEnable;
            this.bolSuper = bolSuper;

            dbData = Integer.parseInt("" + bolNew + bolEnable + bolSuper, 2);
        }

        public void setDbData(Integer dbData) {
            this.dbData = dbData;

            String s = Integer.toBinaryString(dbData);
            int length = s.length();

            Function<Integer, Integer> function = new Function<Integer, Integer>() {

                @Override
                public Integer apply(Integer object) {
                    int index = length - object;
                    return index < 0 ? 0 : Integer.valueOf(s.charAt(index) + "");
                }
            };


            bolNew = function.apply(3);
            bolEnable = function.apply(2);
            bolSuper = function.apply(1);
        }

        public User(Integer dbData) {
            setDbData(dbData);
        }
    }

    public static void main(String[] args) {
        // 针对User类中的三个字段,我们会对应数据库表的三个字段。在某种特殊的情况下,为了节省存储,那么需要将3个字段融合成一个?

        // 我们可以通过位,指定每一位代表的意思,假如顺序是:bolNew - bolEnable - bolSuper

        // 我们通过组合可以得到:000 001 010 011 100 101 110 111
        List<User> list = new ArrayList<>(8);
        Collections.addAll(
                list,
                new User(0),
                new User(1),
                new User(2),
                new User(3),
                new User(4),
                new User(5),
                new User(6),
                new User(7)
        );


        // 如何查询数据库里面是新用户的的数据呢?新用户有100 111 101 110 ,数据 & 100 = 0 就是非新用户, 数据 & 100 = 4 就是新用户
        System.out.println("----------------新用户--------------------");
        list.stream().filter(x -> (x.getDbData() & 4) == 4)
                .collect(Collectors.toList())
                .forEach(x -> {
                    System.out.println("新用户:" + x);
                });

        // 如何查询即是 新用户,又是超级管理员? 数据为:1?1
        System.out.println("----------------新用户和超级管理员--------------------");
        list.stream().filter(x -> (x.getDbData() & 5) == 5)
                .collect(Collectors.toList())
                .forEach(x -> {
                    System.out.println("新用户和超级管理员:" + x);
                });

        // 如何更新数据呢?比如将用户都设置成新用户?我们可以找到非新用户,011 010 001 000,将最前面的位改成1
        System.out.println("----------------非新用户--------------------");
        List<User> collect = list.stream().filter(x -> (x.getDbData() & 4) == 0).collect(Collectors.toList());
        for (User user : collect) {
            System.out.println("非新用户:" + user);
        }

        collect.stream().forEach(x -> {
            x.setDbData(x.getDbData() | 4);
        });

        System.out.println("--------------修改后的非新用户,就是新用户--------------------");
        for (User user : collect) {
            System.out.println("非新用户:" + user);
        }

    }
}

  • 12
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
一、基本概念和术语 数据(Data)  数据是信息的载体。它能够被计算机识别、存储和加工处理,是计算机程序加工的"原料"。  随着计算机应用领域的扩大,数据的范畴包括:  整数、实数、字符串、图像和声音等。 数据元素(Data Element)  数据元素是数据的基本单位。数据元素也称元素、结点、顶点、记录。  一个数据元素可以由若干个数据项(也可称为字段、域、属性)组成。数据项是具有独立含义的最小标识单位。 数据结构(Data Structure)  数据结构指的是数据之间的相互关系,即数据的组织形式。 1.数据结构一般包括以下三方面内容: ① 数据元素之间的逻辑关系,也称数据的逻辑结构(Logical Structure);  数据的逻辑结构是从逻辑关系上描述数据,与数据的存储无关,是独立于计算机的。数据的逻辑结构可以看作是从具体问题抽象出来的数学模型。 ② 数据元素及其关系在计算机存储器内的表示,称为数据的存储结构(Storage Structure);  数据的存储结构是逻辑结构用计算机语言的实现(亦称为映象),它依赖于计算机语言。对机器语言而言,存储结构是具体的。一般,只在高级语言的层次上讨论存储结构。 ③ 数据的运算,即对数据施加的操作。   数据的运算定义在数据的逻辑结构上,每种逻辑结构都有一个运算的集合。最常用的检索、插入、删除、更新、排序等运算实际上只是在抽象的数据上所施加的一系列抽象的操作。  所谓抽象的操作,是指我们只知道这些操作是"做什么",而无须考虑"如何做"。只有确定了存储结构之后,才考虑如何具体实现这些运算。 为了增加对数据结构的感性认识,下面举例来说明有关数据结构的概念。 【例1.1】 学生成绩表,见下表。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

没脸见人555

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值