精华内容
下载资源
问答
  • 数据结构:八大数据结构分类

    万次阅读 多人点赞 2018-09-05 18:23:28
    数据结构分类 数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成 。 常用的数据结构有:数组,栈,链表,队列,树,图,堆,散列表等,如图所示: 每一种数据结构都...

    本文目录:

    数据结构分类

    数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成 。
    常用的数据结构有:数组,栈,链表,队列,树,图,堆,散列表等,如图所示:
    这里写图片描述
    每一种数据结构都有着独特的数据存储方式,下面为大家介绍它们的结构和优缺点。

    1、数组

    数组是可以再内存中连续存储多个元素的结构,在内存中的分配也是连续的,数组中的元素通过数组下标进行访问,数组下标从0开始。例如下面这段代码就是将数组的第一个元素赋值为 1。

    int[] data = new int[100];data[0]  = 1;
    

    优点:
    1、按照索引查询元素速度快
    2、按照索引遍历数组方便

    缺点:
    1、数组的大小固定后就无法扩容了
    2、数组只能存储一种类型的数据
    3、添加,删除的操作慢,因为要移动其他的元素。

    适用场景:
    频繁查询,对存储空间要求不大,很少增加和删除的情况。

    2、栈

    栈是一种特殊的线性表,仅能在线性表的一端操作,栈顶允许操作,栈底不允许操作。 栈的特点是:先进后出,或者说是后进先出,从栈顶放入元素的操作叫入栈,取出元素叫出栈。
    这里写图片描述
    栈的结构就像一个集装箱,越先放进去的东西越晚才能拿出来,所以,栈常应用于实现递归功能方面的场景,例如斐波那契数列。

    3、队列

    队列与栈一样,也是一种线性表,不同的是,队列可以在一端添加元素,在另一端取出元素,也就是:先进先出。从一端放入元素的操作称为入队,取出元素为出队,示例图如下:
    这里写图片描述
    使用场景:因为队列先进先出的特点,在多线程阻塞队列管理中非常适用。

    4、链表

    链表是物理存储单元上非连续的、非顺序的存储结构,数据元素的逻辑顺序是通过链表的指针地址实现,每个元素包含两个结点,一个是存储元素的数据域 (内存空间),另一个是指向下一个结点地址的指针域。根据指针的指向,链表能形成不同的结构,例如单链表,双向链表,循环链表等。
    这里写图片描述
    链表的优点:
    链表是很常用的一种数据结构,不需要初始化容量,可以任意加减元素;
    添加或者删除元素时只需要改变前后两个元素结点的指针域指向地址即可,所以添加,删除很快;

    缺点:
    因为含有大量的指针域,占用空间较大;
    查找元素需要遍历链表来查找,非常耗时。

    适用场景:
    数据量较小,需要频繁增加,删除操作的场景

    5、树

    是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合。把它叫做 “树” 是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:

    • 每个节点有零个或多个子节点;
    • 没有父节点的节点称为根节点;
    • 每一个非根节点有且只有一个父节点;
    • 除了根节点外,每个子节点可以分为多个不相交的子树;

    在日常的应用中,我们讨论和用的更多的是树的其中一种结构,就是二叉树
    这里写图片描述
    二叉树是树的特殊一种,具有如下特点:

    1、每个结点最多有两颗子树,结点的度最大为2。
    2、左子树和右子树是有顺序的,次序不能颠倒。
    3、即使某结点只有一个子树,也要区分左右子树。

    二叉树是一种比较有用的折中方案,它添加,删除元素都很快,并且在查找方面也有很多的算法优化,所以,二叉树既有链表的好处,也有数组的好处,是两者的优化方案,在处理大批量的动态数据方面非常有用。

    扩展:
    二叉树有很多扩展的数据结构,包括平衡二叉树、红黑树、B+树等,这些数据结构二叉树的基础上衍生了很多的功能,在实际应用中广泛用到,例如mysql的数据库索引结构用的就是B+树,还有HashMap的底层源码中用到了红黑树。这些二叉树的功能强大,但算法上比较复杂,想学习的话还是需要花时间去深入的。

    6、散列表

    散列表,也叫哈希表,是根据关键码和值 (key和value) 直接进行访问的数据结构,通过key和value来映射到集合中的一个位置,这样就可以很快找到集合中的对应元素。

    记录的存储位置=f(key)

    这里的对应关系 f 成为散列函数,又称为哈希 (hash函数),而散列表就是把Key通过一个固定的算法函数既所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里,这种存储空间可以充分利用数组的查找优势来查找元素,所以查找的速度很快。

    哈希表在应用中也是比较常见的,就如Java中有些集合类就是借鉴了哈希原理构造的,例如HashMap,HashTable等,利用hash表的优势,对于集合的查找元素时非常方便的,然而,因为哈希表是基于数组衍生的数据结构,在添加删除元素方面是比较慢的,所以很多时候需要用到一种数组链表来做,也就是拉链法。拉链法是数组结合链表的一种结构,较早前的hashMap底层的存储就是采用这种结构,直到jdk1.8之后才换成了数组加红黑树的结构,其示例图如下:
    这里写图片描述
    从图中可以看出,左边很明显是个数组,数组的每个成员包括一个指针,指向一个链表的头,当然这个链表可能为空,也可能元素很多。我们根据元素的一些特征把元素分配到不同的链表中去,也是根据这些特征,找到正确的链表,再从链表中找出这个元素。

    哈希表的应用场景很多,当然也有很多问题要考虑,比如哈希冲突的问题,如果处理的不好会浪费大量的时间,导致应用崩溃。

    7、堆

    堆是一种比较特殊的数据结构,可以被看做一棵树的数组对象,具有以下的性质:

    • 堆中某个节点的值总是不大于或不小于其父节点的值;

    • 堆总是一棵完全二叉树。

    将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。

    堆的定义如下:n个元素的序列{k1,k2,ki,…,kn}当且仅当满足下关系时,称之为堆。
    (ki <= k2i,ki <= k2i+1)或者(ki >= k2i,ki >= k2i+1), (i = 1,2,3,4…n/2),满足前者的表达式的成为小顶堆,满足后者表达式的为大顶堆,这两者的结构图可以用完全二叉树排列出来,示例图如下:
    这里写图片描述
    因为堆有序的特点,一般用来做数组中的排序,称为堆排序。

    8、图

    图是由结点的有穷集合V和边的集合E组成。其中,为了与树形结构加以区别,在图结构中常常将结点称为顶点,边是顶点的有序偶对,若两个顶点之间存在一条边,就表示这两个顶点具有相邻关系。

    按照顶点指向的方向可分为无向图和有向图:
    这里写图片描述
    这里写图片描述
    图是一种比较复杂的数据结构,在存储数据上有着比较复杂和高效的算法,分别有邻接矩阵 、邻接表、十字链表、邻接多重表、边集数组等存储结构,这里不做展开,读者有兴趣可以自己学习深入。

    展开全文
  • 主要介绍了Java常见的几种基本数据结构,包括其含义和用法,,需要的朋友可以参考下
  • 1、数据结构书籍(均可免费下载) 分类我已拆分完成附下: 书籍推荐榜 算法复杂度集锦 排序算法大全 数据结构大纲 2、数据结构视频教程(均免费观看) ...数据结构试题解析 数据结构试题十套...

    1、数据结构书籍(均可免费下载)

    分类我已拆分完成附下:

    (1) 书籍推荐榜
    在这里插入图片描述

    (2) 算法复杂度集锦
    在这里插入图片描述

    (3) 排序算法大全
    在这里插入图片描述

    (4) 数据结构大纲

    ![(https://img-blog.csdnimg.cn/2020042017022216.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDA3NzU1Ng==,size_16,color_FFFFFF,t_70)

    2、数据结构视频教程(均免费观看)

    分类我已拆分完成附下:

    (1) 视频推荐榜及链接地址
    在这里插入图片描述

    (2) 数据结构新手使用网课
    在这里插入图片描述

    (3) 数据结构讲解(韩顺平讲解,需注册)
    在这里插入图片描述

    3、数据结构在线动画

    (1) 数据结构动画展示
    在这里插入图片描述

    4、数据结构试题(免费)

    分类我已拆分完成附下:

    (1) 八类数据结构试题
    在这里插入图片描述

    (2) 八类数据结构试题解析
    在这里插入图片描述

    (3) 数据结构试题十套卷
    在这里插入图片描述

    (4) 数据结构练习系统l(int.code国外源)
    在这里插入图片描述

    (5) 牛客网练习系统
    在这里插入图片描述

    (6) leetcode练习系统(需注册)
    在这里插入图片描述

    (7) 15道易考算法题
    在这里插入图片描述

    (8) 常用算法c++源码(GitHub源,网速可能稍慢)
    在这里插入图片描述

    5、有需要来找我

    联系方式我的链接
    yzqrtop@123.com个人主页
    展开全文
  • Java 八大基本数据类型

    万次阅读 多人点赞 2018-09-11 14:59:48
    1.bit就是位,也叫比特位,是计算机表示数据最小的单位 2.byte就是字节 3.1byte=8bit ,0001 1100,一般用两个16进制来显示,所以我们经常看到1个字节显示为 1c 4.1byte就是1B byte[] bs = {(byte)0xff, 0x0F, 0x1...

    1.bit就是位,也叫比特位,是计算机表示数据最小的单位
    2.byte就是字节
    3.1byte=8bit ,0001 1100,一般用两个16进制来显示,所以我们经常看到1个字节显示为 1c
    4.1byte就是1B

    byte[] bs = {(byte)0xff, 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F};
    for(int i=0;i<bs.length;i++){
        int tempI=(int)(bs[i] & 0xff);
        String temp16=Integer.toHexString(tempI);
        L.w("tan","i="+i+", 10="+tempI +", 16="+temp16);
    }

     

    1. Java的简单类型及其封装器类

    Java基本类型共有八种,基本类型可以分为三类,字符类型char,布尔类型boolean以及数值类型byte、short、int、long、float、double。数值类型又可以分为整数类型byte、short、int、long和浮点数类型float、double。JAVA中的数值类型不存在无符号的,它们的取值范围是固定的,不会随着机器硬件环境或者操作系统的改变而改变。实际上,JAVA中还存在另外一种基本类型void,它也有对应的包装类 java.lang.Void,不过我们无法直接对它们进行操作。8 中类型表示范围如下:

    byte:8位,最大存储数据量是255,存放的数据范围是-128~127之间。

    short:16位,最大数据存储量是65536,数据范围是-32768~32767之间。

    int:32位,最大数据存储容量是2的32次方减1,数据范围是负的2的31次方到正的2的31次方减1。

    long:64位,最大数据存储容量是2的64次方减1,数据范围为负的2的63次方到正的2的63次方减1。

    float:32位,数据范围在3.4e-45~1.4e38,直接赋值时必须在数字后加上f或F。

    double:64位,数据范围在4.9e-324~1.8e308,赋值时可以加d或D也可以不加。

    boolean:只有true和false两个取值。

    char:16位,存储Unicode码,用单引号赋值。

    Java决定了每种简单类型的大小。这些大小并不随着机器结构的变化而变化。这种大小的不可更改正是Java程序具有很强移植能力的原因之一。下表列出了Java中定义的简单类型、占用二进制位数及对应的封装器类。

     

    简单类型

    boolean

    byte

    char

    short

    Int

    long

    float

    double

    void

    二进制位数

    1

    8

    16

    16

    32

    64

    32

    64

    --

    封装器类

    Boolean

    Byte

    Character

    Short

    Integer

    Long

    Float

    Double

    Void

       

    对于数值类型的基本类型的取值范围,我们无需强制去记忆,因为它们的值都已经以常量的形式定义在对应的包装类中了。如:

    基本类型byte 二进制位数:Byte.SIZE最小值:Byte.MIN_VALUE最大值:Byte.MAX_VALUE

    基本类型short二进制位数:Short.SIZE最小值:Short.MIN_VALUE最大值:Short.MAX_VALUE

    基本类型char二进制位数:Character.SIZE最小值:Character.MIN_VALUE最大值:Character.MAX_VALUE

    基本类型double 二进制位数:Double.SIZE最小值:Double.MIN_VALUE最大值:Double.MAX_VALUE

    注意:float、double两种类型的最小值与Float.MIN_VALUE、 Double.MIN_VALUE的值并不相同,实际上Float.MIN_VALUE和Double.MIN_VALUE分别指的是 float和double类型所能表示的最小正数。也就是说存在这样一种情况,0到±Float.MIN_VALUE之间的值float类型无法表示,0 到±Double.MIN_VALUE之间的值double类型无法表示。这并没有什么好奇怪的,因为这些范围内的数值超出了它们的精度范围。

    Float和Double的最小值和最大值都是以科学记数法的形式输出的,结尾的"E+数字"表示E之前的数字要乘以10的多少倍。比如3.14E3就是3.14×1000=3140,3.14E-3就是3.14/1000=0.00314。

    Java基本类型存储在栈中,因此它们的存取速度要快于存储在堆中的对应包装类的实例对象。从Java5.0(1.5)开始,JAVA虚拟机(JavaVirtual Machine)可以完成基本类型和它们对应包装类之间的自动转换。因此我们在赋值、参数传递以及数学运算的时候像使用基本类型一样使用它们的包装类,但这并不意味着你可以通过基本类型调用它们的包装类才具有的方法。另外,所有基本类型(包括void)的包装类都使用了final修饰,因此我们无法继承它们扩展新的类,也无法重写它们的任何方法。

    基本类型的优势:数据存储相对简单,运算效率比较高

    包装类的优势:有的容易,比如集合的元素必须是对象类型,满足了java一切皆是对象的思想

     

    2.Java中的常量

    十六进制整型常量:以十六进制表示时,需以0x或0X开头,如0xff,0X9A。

    八进制整型常量:八进制必须以0开头,如0123,034。

    长整型:长整型必须以L作结尾,如9L,342L。

    浮点数常量:由于小数常量的默认类型是double型,所以float类型的后面一定要加f(F)。同样带小数的变量默认为double类型。

    如:float f;

        f=1.3f;//必须声明f。

    字符常量:字符型常量需用两个单引号括起来(注意字符串常量是用两个双引号括起来)。Java中的字符占两个字节。一些常用的转义字符:

    ①\r表示接受键盘输入,相当于按下了回车键;

    ②\n表示换行;

    ③\t表示制表符,相当于Table键;

    ④\b表示退格键,相当于Back Space键;

    ⑤\'表示单引号;

    ⑥\''表示双引号;

    ⑦\\表示一个斜杠\。

     

    3. 数据类型之间的转换

    1).简单类型数据间的转换,有两种方式:自动转换和强制转换,通常发生在表达式中或方法的参数传递时。

    自动转换

    具体地讲,当一个较"小"数据与一个较"大"的数据一起运算时,系统将自动将"小"数据转换成"大"数据,再进行运算。而在方法调用时,实际参数较"小",而被调用的方法的形式参数数据又较"大"时(若有匹配的,当然会直接调用匹配的方法),系统也将自动将"小"数据转换成"大"数据,再进行方法的调用,自然,对于多个同名的重载方法,会转换成最"接近"的"大"数据并进行调用。这些类型由"小"到"大"分别为 (byte,short,char)--int--long--float—double。这里我们所说的"大"与"小",并不是指占用字节的多少,而是指表示值的范围的大小。

    ①下面的语句可以在Java中直接通过:

    byte b;int i=b; long l=b; float f=b; double d=b;

    ②如果低级类型为char型,向高级类型(整型)转换时,会转换为对应ASCII码值,例如

    char c='c'; int i=c;

    System.out.println("output:"+i);输出:output:99;

    ③对于byte,short,char三种类型而言,他们是平级的,因此不能相互自动转换,可以使用下述的强制类型转换。

    short i=99 ; char c=(char)i; System.out.println("output:"+c);输出:output:c;

    强制转换

    将"大"数据转换为"小"数据时,你可以使用强制类型转换。即你必须采用下面这种语句格式: int n=(int)3.14159/2;可以想象,这种转换肯定可能会导致溢出或精度的下降。

    2)表达式的数据类型自动提升, 关于类型的自动提升,注意下面的规则。

    ①所有的byte,short,char型的值将被提升为int型;

    ②如果有一个操作数是long型,计算结果是long型;

    ③如果有一个操作数是float型,计算结果是float型;

    ④如果有一个操作数是double型,计算结果是double型;

    例, byte b; b=3; b=(byte)(b*3);//必须声明byte。

    3)包装类过渡类型转换

    一般情况下,我们首先声明一个变量,然后生成一个对应的包装类,就可以利用包装类的各种方法进行类型转换了。例如:

    ①当希望把float型转换为double型时:

    float f1=100.00f;

    Float F1=new Float(f1);

    double d1=F1.doubleValue();//F1.doubleValue()为Float类的返回double值型的方法

    ②当希望把double型转换为int型时:

    double d1=100.00;

    Double D1=new Double(d1);

    int i1=D1.intValue();

    简单类型的变量转换为相应的包装类,可以利用包装类的构造函数。即:Boolean(boolean value)、Character(char value)、Integer(int value)、Long(long value)、Float(float value)、Double(double value)

    而在各个包装类中,总有形为××Value()的方法,来得到其对应的简单类型数据。利用这种方法,也可以实现不同数值型变量间的转换,例如,对于一个双精度实型类,intValue()可以得到其对应的整型变量,而doubleValue()可以得到其对应的双精度实型变量。

    4)字符串与其它类型间的转换

    其它类型向字符串的转换

    ①调用类的串转换方法:X.toString();

    ②自动转换:X+"";

    ③使用String的方法:String.volueOf(X);

    字符串作为值,向其它类型的转换

    ①先转换成相应的封装器实例,再调用对应的方法转换成其它类型

    例如,字符中"32.1"转换double型的值的格式为:new Float("32.1").doubleValue()。也可以用:Double.valueOf("32.1").doubleValue()

    ②静态parseXXX方法

    String s = "1";

    byte b = Byte.parseByte( s );

    short t = Short.parseShort( s );

    int i = Integer.parseInt( s );

    long l = Long.parseLong( s );

    Float f = Float.parseFloat( s );

    Double d = Double.parseDouble( s );

    ③Character的getNumericValue(char ch)方法

    5)Date类与其它数据类型的相互转换

    整型和Date类之间并不存在直接的对应关系,只是你可以使用int型为分别表示年、月、日、时、分、秒,这样就在两者之间建立了一个对应关系,在作这种转换时,你可以使用Date类构造函数的三种形式:

    ①Date(int year, int month, int date):以int型表示年、月、日

    ②Date(int year, int month, int date, int hrs, int min):以int型表示年、月、日、时、分

    ③Date(int year, int month, int date, int hrs, int min, int sec):以int型表示年、月、日、时、分、秒

    在长整型和Date类之间有一个很有趣的对应关系,就是将一个时间表示为距离格林尼治标准时间1970年1月1日0时0分0秒的毫秒数。对于这种对应关系,Date类也有其相应的构造函数:Date(long date)。

    获取Date类中的年、月、日、时、分、秒以及星期你可以使用Date类的getYear()、getMonth()、getDate()、getHours()、getMinutes()、getSeconds()、getDay()方法,你也可以将其理解为将Date类转换成int。

    而Date类的getTime()方法可以得到我们前面所说的一个时间对应的长整型数,与包装类一样,Date类也有一个toString()方法可以将其转换为String类。

    有时我们希望得到Date的特定格式,例如20020324,我们可以使用以下方法,首先在文件开始引入,

    import java.text.SimpleDateFormat;

    import java.util.*;

    java.util.Date date = new java.util.Date();

     

    //如果希望得到YYYYMMDD的格式

    SimpleDateFormat sy1=new SimpleDateFormat("yyyyMMDD");

    String dateFormat=sy1.format(date);

     

    //如果希望分开得到年,月,日

    SimpleDateFormat sy=new SimpleDateFormat("yyyy");

    SimpleDateFormat sm=new SimpleDateFormat("MM");

    SimpleDateFormat sd=new SimpleDateFormat("dd");

    String syear=sy.format(date);

    String smon=sm.format(date);

    String sday=sd.format(date);

    总结:只有boolean不参与数据类型的转换

    (1).自动类型的转换:a.常数在表数范围内是能够自动类型转换的

    b.数据范围小的能够自动数据类型大的转换(注意特例)

    int到float,long到float,long到double 是不会自动转换的,不然将会丢失精度

    c.引用类型能够自动转换为父类的

    d.基本类型和它们包装类型是能够互相转换的

    (2).强制类型转换:用圆括号括起来目标类型,置于变量前

     

    4.Java引用类型

    Java有 5种引用类型(对象类型):类 接口 数组 枚举 标注

    引用类型:底层结构和基本类型差别较大

    JVM的内存空间:(1). Heap 堆空间:分配对象 new Student()

    (2). Stack 栈空间:临时变量 Student stu

    (3).Code 代码区 :类的定义,静态资源 Student.class

    eg:Student stu = new Student(); //new 在内存的堆空间创建对象

    stu.study(); //把对象的地址赋给stu引用变量

    上例实现步骤:a.JVM加载Student.class 到Code区

         b.new Student()在堆空间分配空间并创建一个Student实例;

         c.将此实例的地址赋值给引用stu, 栈空间;

    -----------------------------------------  个人总结 -----------------------------------------

    上面是转载别人的文章,下面做个总结:

    1、如果小数类型,并且小数比较小,比如四位小数,建议使用 BigDecimal 如果 是 double 类型会有失精度,有的时候会用科学记数法表示;

    比如 0.0001 会变成 1.0E-4,试问谁能看懂,如果偏要用 double 还要对类型进行转换。

    2、int double 都是有包装类型的,建议使用包装类型,包装类型能区分 null 和 0,就像在spring-mvc接收时使用 int 类型接收值,如果这个属性不传值,ajax 请求会报 400 错误,而且不能区分这个值是否是空;

    3、for 循环中如果要对字符串进行拼接,建议使用 StringBuffer ,如果没有线程安全问题,直接使用 StringBuilder,原因StringBuffer的所有操作是保证线程安全的,可以理解成使用了 synchronized 关键字,对性能是有影响的。

    4、最后对所有包装类型进行操作(比如 toString())要进行空指针判断,我们并不能保证这个值是有的。

    展开全文
  • Java集合与数据结构——七排序算法的实现

    千次阅读 多人点赞 2021-08-01 19:05:22
    基本排序算法

    本文内容介绍大纲

    在这里插入图片描述


    排序介绍


      排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。

      平时的上下文中,如果提到排序,通常指的是排升序(非降序)。

      通常意义上的排序,都是指的原地排序(in place sort)


    稳定性


      两个相等的数据,如果经过排序后,排序算法能保证其相对位置不发生变化,则我们称该算法是具备稳定性的排序算法。


    一、直接插入排序


    算法演示:


    在这里插入图片描述


    1.原理


    整个区间被分为


    1.有序区间

    2.无序区间

      每次选择无序区间的第一个元素,在有序区间内选择合适的位置插入


    2.基本思想


      直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。


    实际中我们玩扑克牌时,就用了插入排序的思想
    在这里插入图片描述

    我们来说一下 直接插入排序的具体步骤:

    在这里插入图片描述

    1.定义一个 变量 i ,i 从这个数组中的第二个元素开始遍历

    在这里插入图片描述

    2.定义 一个变量 j , j = i - 1 .如果 arr[ i ] 比 arr [ j] 小的话,每次都把 arr [ j+1 ] = arr [ j ],相当于把 i 之前 比 arr [ i ] 大的数字全都向后移动一位,直到遇到 arr [ j ] < arr [ i ],此时 arr [j+1] = arr [ i ].

    在这里插入图片描述
    在这里插入图片描述

    3.如果j向前遍历,直到 j<0 时 也没有满足 arr[ i ] < arr [ j], j 向前的遍历结束 , arr [ j+1 ] = arr [ i ].

    4.最后完成遍历,排序完成.

    在这里插入图片描述

    3.代码展示

    在这里插入图片描述
    稳定性判断

    在这里插入图片描述
      根据上面的思路我们进行遍历,发现4 4 的位置并没有进行交换 ,所以 直接插入排序是稳定的.

    还有一种判断稳定性的方法:

      在排序时,如果元素 没有发生跳跃式 变换,只是相邻元素交换的话,这个排序就是稳定的.

      还有通过这个代码我们发现,这个排序也可以变成不稳定的,

    在这里插入图片描述
      在这样的情况下,相同的元素 在比较时就会发生交换,排序变成不稳定的了.

    我们可以得到一个结论:

    一个稳定的排序,可以实现为不稳定的排序

    但是一个本身就不稳定的排序,就不可能实现为稳定的排序

    4.性能分析

    时间复杂度

    最好情况下:

      我们给定一个有序的数组进行直接插入排序,这就是最好情况,此时 时间复杂度为 O (N )

    最坏情况下:

      我们给定一个完全无序的数组进行直接插入排序,这就是最坏情况,此时时间复杂度为 O(N^2).

    在这里插入图片描述

    我们同样得到一个结论:

    当一组数据,数据量不大且 趋近于有序,此时用插入排序时间更快 .
    越有序越快!!

    空间复杂度

    这个排序算法 没用用到其他的辅助空间,所以 空间复杂度 为 O (1).

    稳定性

    这个排序由于没有发生跳跃式 变换,所以是 稳定的

    二、希尔排序

    算法演示:

    在这里插入图片描述

    希尔排序法又称缩小增量法。

    希尔排序是基于插入排序的以下两点性质而提出改进方法的:


    1.插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。

    2.但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。


    1.基本思想


    1. 先选定一个小于N的整数gap作为第一增量,然后将所有距离为gap的元素分在同一组,并对每一组的元素进行直接插入排序。然后再取一个比第一增量小的整数作为第二增量,重复上述操作…

    2.当增量的大小减到1时,就相当于整个序列被分到一组,进行一次直接插入排序,排序完成。

    为什么要让gap由大到小呢?

     gap越大,数据移动得越快;gap越小,数据移动得越慢。开始让gap较大,可以让数据更快得移动到自己对应的位置附近,减少移动次数.


    *注意点


    1.希尔排序是对直接插入排序的优化。

    2. 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。


    我们来将整个排序的 思路走一遍:

    下面是 我们要进行排序的数组
    在这里插入图片描述

      将数组中的元素进行分组,每组中的元素 gap 间隔为3, 我用不同颜色进行分组. 在这里插入图片描述
    gap ==3 ,分组完之后,我们将每一组中的数据进行排序

    在这里插入图片描述

      将数组中的元素进行分组,每组中的元素 gap 间隔为2, 我用不同颜色进行分组.

    在这里插入图片描述
    gap == 2 ,分组完之后,我们将每一组中的数据进行排序

    在这里插入图片描述

      将数组中的元素进行分组,每组中的元素 gap 间隔为1, 此时对整体进行排序.

    在这里插入图片描述

    整体排完序后,希尔排序完成.

    在这里插入图片描述

    每一组排序我们都用的是 直接插入排序.


    2.代码展示


    在这里插入图片描述


    3.增量 gap 的选取


    选自 《数据结构》清华大学出版
    在这里插入图片描述
    gap 的值 没有除 1 以外 的公因子,并且最后一个增量值 必须为 1 .

    我们只能尽量 追求gap 没有公因子, 最后 要 +1.

    我们可以这样取 gap ,使 gap 最后为 1.

       gap = arr.length;
       while(gap>1){
           gap = gap/3+1;  //  加 1  保证最后一个序列为1 ,除几都行
       }
    

    4.性能分析


    时间复杂度

    最坏、最好情况下

      由于 gap 每次取值都不同,所以算起来十分复杂,但是我们仍然能够得到一些数据…

    在这里插入图片描述
    所以我们就这样认为

    最好情况下时间复杂度 O(n^ 1.3)

    最坏情况下时间复杂度 O(n^ 1.5)


    空间复杂度

    没有借助其他的辅助空间,所以空间复杂度 为 O(1)


    稳定性

    在这个排序中 发生了跳跃式的交换,所以这个排序不是稳定的.

    在这里插入图片描述

    三、选择排序


    算法演示:


    在这里插入图片描述


    1.基本思想


     数组从头开始遍历 , i= 0开始,i 后面的每一个元素 arr [ j ] 都与 arr[i] 进行比较,如果 arr [ i ]> arr [ j ] ,那么就进行交换.

    我们根据思路来 走一下排序的过程.

    我们要对 这个数据进行排序
    在这里插入图片描述

    开始进行排序

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    2.代码展示


    在这里插入图片描述


    3.性能分析


    时间复杂度

    最坏情况下: O(n^2)

    最好情况下: O(n^2)


    空间复杂度

    没有借助辅助空间,所以空间复杂度为 O ( 1 )


    稳定性

    因为在排序的过程中发生了跳跃式交换,所以这种排序不是稳定的.

    在这里插入图片描述


    四、堆排序


    算法演示:


    在这里插入图片描述


    1.基本思想


    从小到大排序 —— 升序 建立大堆

    从大到小排序 —— 降序 建立小堆


    思路: 以升序 为 例


    0.先将数组 调整为一个 大堆 ,建立一个大堆

    1. 交换 数组 首尾 的元素,这样最大的堆顶元素 被放在数组的最后一个,此时 最后一个元素 已经定好序了.

    2. 此时从第一个到 倒数第二个再次调整,调整完后将堆顶元素 与倒数第二个元素交换,按照这样的逻辑规律,循环直到 有序.


    我们以实际 例子说明…

    下面以数组 [5, 7, 9 , 3, 1, 8,6,2] 为例进行从小到大排序的演示:


    0.调整为大堆

    在这里插入图片描述

    1.首尾交换

    2.向下调整

    重复此操作直到全部有序

    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述


    最后我们排完序了

    如何将一个数组转换成一个堆呢?


    2.建堆操作


      下面我们给出一个数组,这个数组逻辑上可以看做一颗完全二叉树,但是还不是一个堆,现在我们通过算法,把它构建成一个堆。


      根节点左右子树不是堆,我们怎么调整呢?这里我们从倒数的第一个非叶子节点的子树开始调整,一直调整到根节点的树,就可以调整成堆。


    将一个二叉树 调整为一个 大根堆


    在这里插入图片描述

    这棵二叉树调整为 大根堆 必须将 每颗子树都调整为大根堆.


    3.向下调整


    思想 步骤:

    parent —> 根节点下标

    child —> 孩子节点下标


    1.从最后一棵子树进行调整.

    2. 每颗子树从根节点向下调整,如果左右孩子节点的最大值比这个根节点大,那么值互换,然后 parent 指向 child ,child = 2* parent + 1, 继续向下调整,直到 下标child 超出二叉树 范围.

    3.重复第二步的操作,遍历每一颗子树,直到所有子树全部遍历完成.


    代码实现:


    在这里插入图片描述


    这就是 向下调整的完整过程.


    我们来看整体堆排序的代码展示:


    4.代码展示


    在这里插入图片描述


    5.性能分析


    时间复杂度

    最好最坏情况下,都是 O(n* logn)


    空间复杂度

    没有借助外部空间,空间复杂度为O(1)


    稳定性

    发生了跳跃式的交换,所以是不稳定的.

    在这里插入图片描述

    五、冒泡排序


    算法演示:


    在这里插入图片描述


    1.基本思想


    两两相邻元素进行比较,数值大的元素排到后面。

    比较相邻的元素。如果第一个比第二个大,就交换他们两个。

    对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。

    针对所有的元素重复以上的步骤,除了最后一个。

    我们也可以找到规律:

    这个数组一共有 10个数字

    第 1 个数字比较了 9次, 第 2 个数字比较了 8 次…

    第 i 个数字 比较 10 - i 次


      持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

    我们来 走一遍 冒泡排序的思路:

    在这里插入图片描述
      之后对每一个数字都从头开始比较相邻元素…直到全部排序完成.


    2.代码展示


    在这里插入图片描述


    3.性能分析


    时间复杂度

    最好、最坏情况下都是 O(n^2),在优化下,最好情况是O(n).


    空间复杂度

    没有借助辅助空间,所以空间复杂度为O(1)


    稳定性

    都是相邻元素之间进行排序,所以这个排序是稳定的.


    在这里插入图片描述


    六、快速排序


    1.原理


    1.从待排序区间选择一个数,作为基准值(pivot);通常为最左边的数字.

    2.Partition: 遍历整个待排序区间,将比基准值小的(可以包含相等的)放到基准值的左边,将比基准值大的(可以包含相等的)放到基准值的右边;

    3. 采用分治思想,对左右两个小区间按照同样的方式处理,直到小区间的长度 == 1,代表已经有序,或者小区间的长度 == 0,代表没有数据。


    1. Hoare 法

    在这里插入图片描述


      左边第一个数字下标定义为 start 右边第一个数字下标定义为 end,key 为第一个数字


     end 先向前走,找到 比 key 小的位置,end 找到小于 key 的位置,保持不动,

    start 在向后走,找到比 key 大的位置

    找到之后,交换 start 和 end 的位置,key 的位置一直保持不动

    重复此过程…

    直到 start 和 end 相遇, 将该位置的值 与 key 交换.


    2.挖坑法

    在这里插入图片描述


    左边第一个数字下标定义为 start 右边第一个数字下标定义为 end


    先将第一个数据放到 临时变量 tmp 中,形成一个坑位

     end 开始向前走,找到比 tmp 小的位置,找到后 ,将该值放入坑位中,该位置形成新的坑位

     start 开始向后移动,找到比 tmp 大的位置,找到后,将该值放入坑位中,再形成新的坑位

    重复上面的两个过程…

    最后 start 和 end 相互遇见,将 tmp 的值 放入最后一个 相遇的坑位.


    我们来走一遍 挖坑法 的具体思路:


    在这里插入图片描述


    2.代码展示


    1.递归思路


    在这里插入图片描述

    2.基准值的选择

    1. 选择边上(左或者右)
    2. 随机选择
    3. 几数取中(例如三数取中):array[left], array[mid], array[right] 大小是中间的为基准值

    快速排序的优化

    1.选择基准值很重要,通常使用几数取中法


      我们如果选取的 在基准的数值正好是 这组数据的中位数,每次都是平均 分,那么此时 时间复杂度最小,但是实际情况中通常没有那么巧合,所以我们为了追求尽可能小的 时间复杂度,取 这组数据 头 、尾 、 中间三个数字中的中间值作为 基准.


    我们在实现 paitition 函数时,要满足这个条件:


    arr [ mid] <= arr [ start ] <= arr [ end ]


    2.partition 过程中把和基准值相等的数也选择出来

    在这里插入图片描述


    3.待排序区间小于一个阈值时(例如 48),使用直接插入排序


      随着递归的进行,数据的区间在缩小,区间的数据也在慢慢趋近于有序…


    在这里插入图片描述

    3.非递归思路

    1.调用 partition 之后,找到了 pivot

    2.把当前 pivot 的左边区间 和右边区间 的下标放入栈中

    3.判断栈是否为 空,不为空,弹出栈顶2个元素,注意: 放的顺序 决定了 取出的顺序中第一个元素是给的 high 还是 low.

    4.再进行 partion

    什么时候 入栈?

    当这个区间 最起码有 2个元素的时候

    代码展示:

    在这里插入图片描述


    3.性能分析


    时间复杂度

    最好的情况下,选完基准之后都均分,此时时间复杂度为O(n*logn)
    最坏的情况下, 数组为一个有序的数组,我们要逆序,此时时间复杂度为 O(n^2).

    空间复杂度

    最好情况下是每次都二分,所以空间复杂度为O(logn),最坏情况下为 O(n),所以 空间复杂度为 O(logn)~ O(n).

    稳定性

    排序时发生了跳跃式交换,所以是不稳定的

    在这里插入图片描述

    七、归并排序


    归并算法演示


    在这里插入图片描述

    1.原理总览


     归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。


    根据思路我们来将 归并排序走一遍:

    1.整组元素对半拆分,拆分之后再次进行拆分,直到拆分成单个的元素.

    2.按其拆分的方式,对其对应的两个元素进行排序并合并成一组.

    3.对合并过的组,每两组再次进行合并


    在这里插入图片描述


    在这个思路中 最重要的 就只有两步:


    1.分解,我们可以折半分解,直到 每个元素都分开

    2.合并 ,将各个元素有序合并.


    2.合并两个有序数组


    我们可以根据 start、mid、end 得到两个数组的区间

    [ start , mid ] ---- [ mid+1 , end ]

    构建一个 辅助的数组空间.

    我们在排序时,有以下几种情况


     两个数组都未遍历完, s1<= e1 && s2<=e2 , 两个同时遍历,谁小往辅助数组放元素.放完之后 ,辅助元素的下标 ++ ,放到数组元素也 ++.

    有一个数组遍历完了,直接在 已经排好序的数组之后接上 未遍历完的.


    合并数组的代码展示:


    在这里插入图片描述


    3.代码展示


    归并排序的完整代码展示:


    在这里插入图片描述


    4.性能分析


    时间复杂度

    因为要进行二分拆解,所以最好、最坏情况下都是 O(n* logn)

    空间复杂度

    由于在合并有序数组是借助了 辅助空间,所以 空间复杂度为 O(n).

    稳定性

    每次排序都是相邻的元素之间比较,所以是稳定的.

    在这里插入图片描述

    八、内部排序


      我们学习了这几种基于比较的排序算法,下面我们来进行总结一下.

    在这里插入图片描述

    在这里插入图片描述

      我们学的排序都是内部排序,什么是内部排序呢? 就是把数据放在内存中 进行排序 .


    内排序:数据量相对少一些,可以放到内存中进行排序。

    外排序:数据量较大,内存中放不下,数据只能放到磁盘文件中,需要排序。

    上面介绍的排序算法均是在内存中进行的,对于数据量庞大的序列,上面介绍的排序算法都束手无策,而归并排序却能胜任这种海量数据的排序。

    九、海量数据的排序问题


    外部排序:排序过程需要在磁盘等外部存储进行的排序

    前提:内存只有 1G,需要排序的数据有 100G


       因为内存中因为无法把所有数据全部放下,所以需要外部排序,而归并排序是最常用的外部排序


    1.先把文件切分成 200 份,每个 512 M

    2.分别对 512 M 排序,因为内存已经可以放的下,所以任意排序方式都可以

    3.进行 200 路归并,同时对 200 份有序文件做归并过程,最终结果就有序了


    在这里插入图片描述



      好了今天的知识就分享到这里,希望大家多多练习,熟练掌握,感谢大家的欣赏与关注!!


    谢谢欣赏!!


    未完待续…

    展开全文
  • Java数据结构和算法

    2018-09-29 11:41:03
    (1)数据结构与算法概念解析 (2)数据结构之数组 (3)数据结构之栈 (4)数据结构之队列 (5)数据结构之链表 (6)数据结构之二叉树 (7)数据结构之霍夫曼树 (8)数据结构之红黑树(一)——基础分析 ...
  • Java数据结构与算法入门

    万次阅读 多人点赞 2018-04-29 11:53:50
    第一部分:Java数据结构要理解Java数据结构,必须能清楚何为数据结构数据结构:Data_Structure,它是储存数据的一种结构体,在此结构中储存一些数据,而...数据结构Java的语言体系中按逻辑结构可以分为两类:线...
  • Java面试题-数据结构

    千次阅读 2018-12-28 16:48:48
    八大基本数据结构以及衍生相关数据结构
  • java数据结构算法

    千人学习 2019-11-22 10:12:46
    做一门精致,全面详细的 java数据结构与算法!!! 让天下没有难学的数据结构, 让天下没有难学的算法, 不吹不黑,我们的讲师及其敬业,可以看到课程视频,课件,代码的录制撰写,都是在深夜,如此用心,其心可鉴,他不掉头发,谁...
  • Java 八大排序算法

    千次阅读 多人点赞 2019-04-30 22:41:08
    数据结构 + 算法 是我们编程的灵魂,其中一个都不能缺少,数据结构我们要掌握的也就那几种,算法也一样,其中排序算法是我们最常见的,也是面试、考核中最为广泛的,在 Java 的世界中我们需要掌握八大排序算法,这是...
  • 数据结构——八大排序算法(面试必备)

    万次阅读 多人点赞 2021-04-24 14:38:41
    目录1. 交换排序——冒泡排序2....从要排序序列的第一个元素开始,一次比较相邻元素的值,发现逆序则交换,将值较的元素逐渐从前向后移动。 public void bubbleSort(int[] arr){ for (int i = 0; i < arr.le...
  • 什么是数据结构? 官方解释:数据结构是一门研究非数值计算的程序设计问题中的操作对象,以及他们之间的关系和操作等相关问题的学科。 大白话:数据结构就是把数据元素按照一定的关系组织起来的集合,用来组成和...
  • 数据结构排序算法系列】数据结构八大排序算法

    万次阅读 多人点赞 2016-03-25 22:36:40
    如Windows操作系统的文件管理中会自动对用户创建的文件按照一定的规则排序(这个规则用户可以自定义,默认按照文件名排序)因此熟练掌握各种排序算法是非常重要的,本博客将对数据结构中常见的八大排序算法进行详细...
  • 图解Java数据结构和算法

    万人学习 2019-06-21 10:09:16
    教程内容:本教程是使用Java来讲解数据结构和算法,考虑到数据结构和算法较难,授课采用图解加算法游戏的方式。内容包括: 稀疏数组、单向队列、环形队列、单向链表、双向链表、环形链表、约瑟夫问题、栈、前缀、中缀...
  • Java八大基本数据类型详解

    万次阅读 2020-12-04 11:06:42
    自从Java发布以来,基本数据类型就是Java语言的一部分,分别是 byte, short, int, long, char, float, double, boolean .当然围绕着这些基本数据类型衍生出来了很多面试题,但是说实话,工作中基本用不到
  • Java数据结构总结

    千次阅读 2018-11-01 20:59:06
    Java 基本数据类型总结 在Java的代码重构中,我们不得不承认若是不了解jvm的内存原理或是数据类型,我们根本读不懂那些乱七八糟的数据参数。 变量就是申请内存来存储值。也就是说,当创建变量的时候,需要在内存中...
  • JAVA内置数据结构概述

    千次阅读 2016-03-12 13:35:36
    内存单位的转换 JAVA基本数据类型和转换 串,数组,集合 包装类 一、内存单位的转换8bit(位)=1Byte(字节) 1024Byte(字节)=1KB 1024KB=1MB ...Java四类种基本数据类型: 第一类:整型 byte short i
  • Java容器(数据结构)—数组详解及运用 一.数组的定义: 数组是一种用于存放 **相同对象 **, 连续存放 , 大小不可改变的 一种容器. ##二. 数组的应用场景(优点) 1.需要的对象数量固定,或在某个范围 2.不需要改变容器...
  • java八大基本数据类型及其封装类

    万次阅读 多人点赞 2019-01-05 16:52:19
    Java基本类型共有种,基本类型可以分为三类,字符类型char,布尔类型boolean以及数值类型byte、short、int、long、float、double。数值类型又可以分为整数类型byte、short、int、long和浮点数类型float、double。...
  • 如何理解并掌握 Java 数据结构

    千次阅读 多人点赞 2019-11-13 11:11:45
    Jack和大家一起来重温《Java数据结构》经典之作。 第一部分:Java数据结构 要理解Java数据结构,必须能清楚何为数据结构数据结构: Data_Structure,它是储存数据的一种结构体,在此结构中储存一些数据,而这些...
  • java中常见的几种数据结构

    千次阅读 2019-05-20 20:50:57
    数据结构相对于算法来说简直是屈指可数,常见的数据结构也就那几种,很容易掌握,但算法可以有成千上万,要想全部掌握基本上很难,我们常说的数据...数组算是最简单的一种数据结构了,在java中数组的类型只要不是Ob...
  • java 数据结构有哪些?

    千次阅读 2012-06-17 23:19:49
    1. java八大基本数据类型及其包装类: boolean : Boolean, byte:Byte, short:Short, int:Integer, long:Long, float:Float, double:Double 2. String 字符串类型 3. 容器类  collection —— List  |—— Set
  • Java学习手册:数据结构与算法汇总

    千次阅读 2019-08-15 09:51:07
    2、Java学习手册:(数据结构与算法-链表)如何实现单链表的增删操作? 3、Java学习手册:(数据结构与算法-链表)如何实现单链表排序? 4、Java学习手册:(数据结构与算法-链表)如何从链表中删除重复元素? 5...
  • Java基础(一) 八大基本数据类型

    千次阅读 2019-06-16 23:28:46
    J2SE入门(一) 八大基本数据类型 自从Java发布以来,基本数据类型就是Java语言的一部分,分别是***byte, short, int, long, char, float, double, boolean***. 其中: 整型:byte, short, int, long 字符型:char ...
  • Java实现八大排序算法

    千次阅读 多人点赞 2021-03-11 17:27:40
    简单选择排序 3.1基本思想 每一次从无序区间选出最大(或最小)的一个元素,存放在无序区间的最后(或最前),直到全部待排序的数据元素排完 。 3.2具体方法 第一趟,从n 个记录中找出关键码最小的记录与第一个记录...
  • 数据结构与算法(java版)

    千次阅读 多人点赞 2017-12-28 21:50:08
    (1)数据结构与算法概念解析 (2)数据结构之数组 (3)数据结构之栈 (4)数据结构之队列 (5)数据结构之链表 (6)数据结构之二叉树 (7)数据结构之霍夫曼树 (8)数据结构之红黑树(一)——基础分析 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 106,068
精华内容 42,427
关键字:

java八大数据结构

java 订阅
数据结构 订阅