【数据结构(一)】初识数据结构

news2025/1/12 12:18:49

❣博主主页: 33的博客❣
▶文章专栏分类: Java从入门到精通◀
🚚我的代码仓库: 33的代码仓库🚚
🫵🫵🫵关注我带你学更多数据结构知识

在这里插入图片描述

目录

  • 1.前言
  • 2.集合架构
  • 3.时间和空间复杂度
    • 3.1算法效率
    • 3.2时间复杂度
      • 3.2.1大O的渐进表示
      • 3.2.2常见时间复杂度举例
    • 3.3空间复杂度
  • 4.包装类
    • 4.1基本数据和对应的包装类:
    • 4.2装箱和拆箱
  • 5.泛型
    • 5.1引出范型
    • 5.2语法
    • 5.3泛型类的使用
    • 5.4泛型是如何编译
    • 5.5泛型的上界
    • 5.6泛型方法
  • 6.总结

1.前言

数据结构是计算机存储,组织数据的方式,指相互之间存在一种或多种特定关系的数据元素的集合,从这篇文章开始,我们将一起进入数据结构的学习,那么该如何学好数据结构呢?博主的建议是多写代码,多思考,多画图!

本章重点

掌握数据结构基本知识主要包括集合框架,时间和空间复杂度,算法效率,大O渐进表示,包装类,泛型相关知识。


2.集合架构

Java 集合框架Java Collection Framework ,又被称为容器和其实现类classes 。
类和接口总览:
在这里插入图片描述


3.时间和空间复杂度

遇到一个算法,我们怎么衡量一个算法的好坏呢?

3.1算法效率

算法效率分析分为两种:第一种是时间效率,第二种是空间效率。时间效率被称为时间复杂度,而空间效率被称作空间复杂度。

3.2时间复杂度

时间复杂度的定义:在计算机科学中,算法的时间复杂度是一个数学函数,它定量描述了该算法的运行时间。一个算法执行所耗费的时间,从理论上说,是不能算出来的,只有你把你的程序放在机器上跑起来,才能知道。但是我们需要每个算法都上机测试吗?是可以都上机测试,但是这很麻烦,所以才有了时间复杂度这个分析方式。一个算法所花费的时间与其中语句的执行次数成正比例,算法中的基本操作的执行次数,为算法的时间复杂度

有些算法的时间复杂度存在最好、平均和最坏情况:

最坏情况:任意输入规模的最大运行次数(上界)当说时间复杂度一般值最坏情况下
平均情况:任意输入规模的期望运行次数
最好情况:任意输入规模的最小运行次数(下界)

3.2.1大O的渐进表示

在计算时间复杂度时,我们不需要计算精确的执行次数,只需要大概的次数,那么我们就剋用大O渐进表示法去掉那些对结果影响不大的项,简明表示执行的次数。
规则:

1、用常数1取代运行时间中的所有加法常数。
2、在修改后的运行次数函数中,只保留最高阶项。
3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。

3.2.2常见时间复杂度举例

例1.

void func2(int N) {
    int count = 0;
    for (int k = 0; k < 2 * N ; k++) {
        count++;       //时间复杂度2N
    }
    int M = 10;
    while ((M--) > 0) {
        count++;	//时间复杂度10
    }
    System.out.println(count);
 }

时间复杂度2N+10 为O(N)


例2.

void func3(int N, int M) {
    int count = 0;
    for (int k = 0; k < M; k++) {
        count++;   //时间复杂度M
    }
    for (int k = 0; k < N ; k++) {
        count++;	//时间复杂度N
    }
    System.out.println(count);
 }

时间复杂度M+N为O(M+N)


例3.

// 计算func4的时间复杂度?
void func4(int N) {
    int count = 0;
    for (int k = 0; k < 100; k++) {
        count++;	//时间复杂度100
    }
    System.out.println(count);
 }

时间复杂度100为O(1)


例4.

// 计算bubbleSort的时间复杂度?
void bubbleSort(int[] array) {
    for (int end = array.length; end > 0; end--) {
        boolean sorted = true;
        for (int i = 1; i < end; i++) {
            if (array[i - 1] > array[i]) {
                Swap(array, i - 1, i);
                sorted = false;
            }
        }
        if (sorted == true) {
            break;
        }
    }
 }

假设array.length=N,那么第一次循环执行N-1次,第二次循坏执行N-2次,第三次循环执行N-3…最后一次为1,那么总次数就是(N-1)+(N-2)+(N-3)+…1,等差数列求和结果为(NN-N)/2那么时间复杂度为O(NN)。


例5.

int binarySearch(int[] array, int value) {
    int begin = 0;
    int end = array.length - 1;
    while (begin <= end) {
        int mid = begin + ((end-begin) / 2);
        if (array[mid] < value)
            begin = mid + 1;
        else if (array[mid] > value)
            end = mid - 1;
        else
            return mid;
    }
    return -1;
 }

在这里插入图片描述
那么剩下1个数就需要时间复杂度O(log2^N)


例6.

// 计算阶乘递归factorial的时间复杂度?
long factorial(int N) {
    return N < 2 ? N : factorial(N-1) * N;
 }

递归复杂度=递归次数*每次递归后执行的次数
时间复杂度=(N-1)*1=O(N)


例7.

int fibonacci(int N) {
    return N < 2 ? N : fibonacci(N-1)+fibonacci(N-2);
 }//2^n

3.3空间复杂度

空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度 。空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。空间复杂度计算规则基本跟时间复杂度类似,也使用大O渐进表示法。


例1.

void bubbleSort(int[] array) {
    for (int end = array.length; end > 0; end--) {
        boolean sorted = true;
        for (int i = 1; i < end; i++) {
            if (array[i - 1] > array[i]) {
                Swap(array, i - 1, i);
                sorted = false;
            }
        }
 
        if (sorted == true) {
            break;
        }
        }
       }
   //输出O(1)

例2.

int[] fibonacci(int n) {
 long[] fibArray = new long[n + 1];
 fibArray[0] = 0;
 fibArray[1] = 1;
 for (int i = 2; i <= n ; i++) {
 fibArray[i] = fibArray[i - 1] + fibArray [i - 2];
 }
 return fibArray;
 }
 //O(N)

4.包装类

在Java中,由于基本类型不是继承自Object,为了在泛型代码中可以支持基本类型,Java给每个基本类型都对应了一个包装类型。

4.1基本数据和对应的包装类:

基本数据类型包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

4.2装箱和拆箱

Integer a = 10;//装箱
int b = 20;
Integer c=b;//基本类型转变为包装类型
Integer a = 10;
int c = a;//拆箱,包装类型转换为基本类型

public static void main(String[] args) {
 Integer a = 127;
 Integer b = 127;
 Integer c = 128;
 Integer d = 128;
 System.out.println(a == b);//true
 System.out.println(c == d);//false
 }

为什么输出结果一个是T一个是F呢,我们来看看源码
在这里插入图片描述
通过源码我们知道,如果范围在【-128,127】那么就返回数组中的值,否则就new一个对象。127在范围内,那么直接返回cache[255]的值;128不在范围内,久new一个 对象。


5.泛型

泛型:就是适用于许多许多类型。从代码上讲,就是对类型实现了参数化。

5.1引出范型

实现一个类,类中包含一个数组成员,使得数组中可以存放任何类型的数据,也可以根据成员方法返回数组中某个下标的值?

class MyArray {
    public Object[] array = new Object[10];
    public Object getPos(int pos) {
        return this.array[pos];
    }
    public void setVal(int pos,Object val) {
        this.array[pos] = val;
    }    
 }
 public class TestDemo {
    public static void main(String[] args) {
        MyArray myArray = new MyArray();
        myArray.setVal(0,10);
        myArray.setVal(1,"hello");//字符串也可以存放
        String ret = myArray.getPos(1);//编译报错
        //强行转化
        String ret =(String)myArray.getPos(1);
        System.out.println(ret);
    }
 }

但是我们发现,虽然任何类型的数据都可以存放,但是获得的时候报错,必须强制转换。但是,当代码很多的变量的时候,我们就不知道该变量是什么类型的,每次都要返回定义的时候去查看是什么类型,就比较繁琐。更多情况下,我们还是希望他只能够持有一种数据类型。而不是同时持有这么多类型。所以,泛型的主要目的:就是指定当前的容器,要持有什么类型的对象。让编译器去做检查。此时,就需要把类型,作为参数传递。需要什么类型,就传入什么类型。


5.2语法

class MyArray<T> {//添加< >表示这个类是泛型
    public T[] array = (T[])new Object[10];//这句代码是错误的,这样写只是为了不让编译器报错
    public T getPos(int pos) {
        return this.array[pos];
    }
    public void setVal(int pos,T val) {
        this.array[pos] = val;
    }
 }
 public class TestDemo {
    public static void main(String[] args) {
        MyArray<Integer> myArray = new MyArray<>();
        //传入<Integer>后,每次存储数据时会检查存入的数据是不是我传入的类型,获取数据的时候也不需要强制转化。
        myArray.setVal(0,10);
        myArray.setVal(1,12);
        int ret = myArray.getPos(1);
        System.out.println(ret);
        myArray.setVal(2,"bit");
    }
 }

5.3泛型类的使用

语法:


泛型类<参数类型> 变量名; //定义一个泛型类引用
MyArray<Integer> a;
new  泛型类<类型实参>(构造方法实参); // 示例化一个泛型类对象
MyArray<Integer> myArray = new MyArray<>();

5.4泛型是如何编译

在编译过程中将所有的T替换为object,这种机制称为擦除机制,在运行的时候并没有泛型的概念。
通过命令:javap -c 查看字节码文件,所有的T都是Object:
在这里插入图片描述
在编译的过程当中,将所有的T替换为Object这种机制,我们称为:擦除机制。
Java的泛型机制是在编译级别实现的。

实例化的时候不能实例化一个泛型数组。

T[] a=new T[5];//这样定义泛型是错误的,这个时候我们不知道到底定义的什么类型的数组
//以我们现在的知识,一般定义数组的时候,我们采取以下方式:
object[] a=new obje[5];

5.5泛型的上界

在定义泛型类时,有时需要对传入的类型变量做一定的约束,可以通过类型边界来约束。
语法

class 泛型类名称<类型形参 extends 类型边界> {
    ...
 }
MyArray<Integer> l1;        // 正常,因为 Integer 是 Number 的子类型
MyArray<String> l2;     // 编译错误,因为 String 不是 Number 的子类型

5.6泛型方法

定义语法:

方法限定符 <类型形参列表> 返回值类型 方法名称(形参列表) { ... }

示例:

public class Util {
    //静态的泛型方法 需要在static后用<>声明泛型类型参数
    public static <E> void swap(E[] array, int i, int j) {
        E t = array[i];
        array[i] = array[j];
        array[j] = t;
    }
 }
 //使用
 Integer[] a = { ... };
 Util.swap(a, 0, 9);//使用类型推导
 Util.<Integer>swap(a, 0, 9);//不使用类型推导

6.总结

本篇介绍数据结构基本知识主要包括集合框架,时间和空间复杂度,算法效率,大O渐进表示,包装类,泛型相关知识,其中关于用泛型定义数组的内容,博主比并没有深入讲解,感兴趣的同学可以查看其他博主的内容。

下期预告:顺序表

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1570198.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity类银河恶魔城学习记录12-4 p126 Item Tooltip源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili UI.cs using System.Collections; using System.Collections.Generic; usi…

AD20全流程的使用笔记

目录 首先一个完整的AD工程文件需要我们自己建立的文件有这些&#xff1a; 新建工程&#xff1a; 从现有的工程文件中将元件添加到原理图库&#xff1a; 元件的摆放&#xff1a; 器件的复制及对齐&#xff1a; 导线、Netlabe、端口的添加&#xff1a; Value值的校对&…

每日一练 寻找两个正序数组的中间数

题目参上&#xff0c;以下是解题思路&#xff1a; 首先&#xff0c;我们应该想到的一种方法是把两数组合并为一个整体的数组&#xff0c;然后返回其中位数即可。那么我们如何合并两数组呢&#xff1f;我们可以用归并排序&#xff0c;设置上下两指针&#xff0c;不断遍历返回较…

idea Springboot校园新闻系统VS开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 springboot 校园新闻发布系统是一套完善的信息系统&#xff0c;结合springboot框架和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用springboot框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和数据库&a…

LeetCode-217存在重复的元素

217 存在重复的元素 给定一个整数数组&#xff0c;判断是否存在重复元素。 如果存在一值在数组中出现至少两次&#xff0c;函数返回 true 。如果数组中每个元素都不相同&#xff0c;则返回 false 。 JavaScript的 Array 对象是用于构造数组的全局对象&#xff0c;数组是类似…

如何在iPhone上恢复永久删除的照片?

2007 年&#xff0c;Apple Inc. 推出了这款震撼人心的智能手机&#xff0c;后来被称为 iPhone。您会惊讶地发现&#xff0c;迄今为止&#xff0c;Apple Inc. 已售罄 7 亿台 iPhone 设备。根据 2023 年 8 月的一项调查数据&#xff0c;95% 的智能手机利润都落入了苹果公司的口袋…

【Vue】watch监听复杂数据,新值与旧值一样

问题 watch监听复杂数据&#xff0c;例如数组&#xff0c;旧值与新值一样 解决方案 监听回调里返回新数组&#xff0c;新、旧数组地址改变&#xff0c;得到的值也就不一样&#xff0c;例↓ ()>[...data] 码 test.js // 数据 const musicList ref([{ id: 540000200805…

兑换码生成算法

兑换码生成算法 兑换码生成算法1.兑换码的需求2.算法分析2.重兑校验算法3.防刷校验算法 3.算法实现 兑换码生成算法 兑换码生成通常涉及在特定场景下为用户提供特定产品或服务的权益或礼品&#xff0c;典型的应用场景包括优惠券、礼品卡、会员权益等。 1.兑换码的需求 要求如…

软考--软件设计师(软件工程总结2)

目录 1.测试方法 2.软件项目管理 3.软件容错技术 4.软件复杂性度量 5.结构化分析方法&#xff08;一种面向数据流的开发方法&#xff09; 6.数据流图 1.测试方法 软件测试&#xff1a;静态测试&#xff08;被测程序采用人工检测&#xff0c;计算机辅助静态分析的手段&…

MyBatis 解决上篇的参数绑定问题以及XML方式交互

前言 上文:MyBatis 初识简单操作-CSDN博客 上篇文章我们谈到的Spring中如何使用注解对Mysql进行交互 但是我们发现我们返回出来的数据明显有问题 我们发现后面三个字段的信息明显没有展示出来 下面我们来谈谈解决方案 解决方案 这里的原因本质上是因为mysql中和对象中的字段属性…

构建未来交通:香橙派OPI Airpro上的智能交通监管系统

引言&#xff1a; 随着城市化进程的加速&#xff0c;交通管理变得越来越复杂。 传统的交通监管系统往往无法有效应对日益增长的车辆数量和复杂的交通状况。因此&#xff0c;我们需要一种更加智能和自适应的解决方案来提高交通效率并减少事故发生率。 香橙派OPI Airpro以其强大的…

07 - D触发器

---- 整理自B站UP主 踌躇月光 的视频 1. 电路实现 将 D 接到 S 端&#xff0c;D 取反接到 R 端&#xff0c;两个输入合成一个输入&#xff0c;R 和 S 总是相反的&#xff0c;就构成了 D 触发器。再添加一个EN&#xff0c;作为锁存功能&#xff0c;EN0 时&#xff0c;R 和 S 都…

Mac删除软件,动一动手指,几秒就彻底删除 mac删除软件删不掉的解决方法 mac删除软件后怎么删除软件数据

当你入职新公司&#xff0c;接手前任员工使用的Mac电脑时&#xff0c;很可能会遇到一个非常普遍的问题&#xff1a;电脑中装有大量你不需要的软件。这些软件不仅占用宝贵的硬盘空间&#xff0c;还可能影响电脑的运行速度和效率。为了获得一个干净、清爽的使用体验&#xff0c;删…

Go协程池gopool源码解析

1、gopool简介 Repository&#xff1a;https://github.com/bytedance/gopkg/tree/develop/util/gopool gopool is a high-performance goroutine pool which aims to reuse goroutines and limit the number of goroutines. It is an alternative to the go keyword. gopool的…

【Java基础知识总结 | 第十篇】HashSet底层实现原理

文章目录 10.HashSet底层实现原理10.1HashSet特点10.2HashSet源码10.3 add流程10.4总结 10.HashSet底层实现原理 10.1HashSet特点 存储对象&#xff1a;HashSet 存储对象采用哈希表的方式&#xff0c;它不允许重复元素&#xff0c;即集合中不会包含相同的元素。当向 HashSet …

Linux_进程信号_7

文章目录 1.什么是信号2.信号列表3.信号处理常见方式4.信号的存储5.信号产生前-中-后1.信号产生前2.信号产生中 6产生信号1.signal2.kill3.raise4.abort5.alarm6.硬件异常 7.core dump8.信号产生中1. sigset_t&#xff08;数据类型&#xff09;2.信号集操作函数1.sigprocmask2.…

Vue3_2024_7天【回顾上篇watch常见的后两种场景】___续

Vue3中监听多条数据的两种使用 1.watch【使用上一章写法&#xff0c;监听两个属性&#xff0c;然后执行相应操作…】 2.watchEffect【相对于使用watch&#xff0c;watchEffect默认页面初始加载&#xff0c;有点类似加配置&#xff1a;立即执行 immediate】 代码&#xff1a; …

Python:百度AI开放平台——OCR图像文字识别应用

一、注册百度AI开放平台 使用百度AI服务的步骤为&#xff1a; 注册&#xff1a;注册成为百度AI开放平台开发者&#xff1b;创建AI应用&#xff1a;在百度API开放平台上创建相关类型的的AI应用&#xff0c;获得AppID、API Key和Secret Key&#xff1b;调用API&#xff1a;调用…

Word中插入Endnote参考文献时显示乱码

近期在写文章需要插入参考文献&#xff0c;使用Endnote插入时显示乱码&#xff0c;如下图所示&#xff1a; 文章末尾显示{ADDIN EN REFILIST } 解决方法 在网上找了诸多方法尝试也没有解决&#xff0c;最终找到一篇博客介绍了一种方法&#xff1a; word选项—高级&#xff1…

苍穹外卖07(缓存菜品,SpringCache,缓存套餐,添加购物车菜品和套餐多下单,查看购物车,清除购物车,删除购物车中一个商品)

目录 一、缓存菜品 1 问题说明 2 实现思路 3 代码开发&#xff1a;修改DishServiceImpl 4 功能测试 二、SpringCache 1. 介绍 2. 使用语法 1 起步依赖 2 使用要求 3 常用注解 4 SpEL表达式(了解备用) 5 步骤小结 3.入门案例 1 准备环境 2 使用入门 1 引导类上加…