Java数据结构和算法-数组、冒泡、选择、插入排序算法、栈、队列、堆

Java数据结构和算法

在这里插入图片描述
算法的五个特征  ①、有穷性 ②、确定性 ③、可行性 ④、有输入 ⑤、有输出
算法的设计原则 ①、正确性 ②、可读性 ③、健壮性  ④、高效率与低存储量需求

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

Java数据结构和算法(二)——数组

第一种方式:
数据类型 [] 数组名称 = new 数据类型[数组长度];
第二种方式:
数据类型 [] 数组名称 = {数组元素1,数组元素2,…}

3、分析数组的局限性
  通过上面的代码,我们发现数组是能完成一个数据结构所有的功能的,而且实现起来也不难,那数据既然能完成所有的工作,我们实际应用中为啥不用它来进行所有的数据存储呢?那肯定是有原因呢。
  数组的局限性分析:
  ①、插入快,对于无序数组,上面我们实现的数组就是无序的,即元素没有按照从大到小或者某个特定的顺序排列,只是按照插入的顺序排列。无序数组增加一个元素很简单,只需要在数组末尾添加元素即可,但是有序数组却不一定了,它需要在指定的位置插入。
  ②、查找慢,当然如果根据下标来查找是很快的。但是通常我们都是根据元素值来查找,给定一个元素值,对于无序数组,我们需要从数组第一个元素开始遍历,直到找到那个元素。有序数组通过特定的算法查找的速度会比无需数组快,后面我们会讲各种排序算法。
  ③、删除慢,根据元素值删除,我们要先找到该元素所处的位置,然后将元素后面的值整体向前面移动一个位置。也需要比较多的时间。
  ④、数组一旦创建后,大小就固定了,不能动态扩展数组的元素个数。如果初始化你给一个很大的数组大小,那会白白浪费内存空间,如果给小了,后面数据个数增加了又添加不进去了。

Java数据结构和算法(三)——冒泡、选择、插入排序算法

冒泡排序解释:(0( N2))
  冒泡排序是由两个for循环构成,第一个for循环的变量 i 表示总共需要多少轮比较,第二个for循环的变量 j 表示每轮参与比较的元素下标【0,1,…,length-i】,因为每轮比较都会出现一个最大值放在最右边,所以每轮比较后的元素个数都会少一个,这也是为什么 j 的范围是逐渐减小的。相信大家理解之后快速写出一个冒泡排序并不难。
2、选择排序 O(N2)
  选择排序是每一次从待排序的数据元素中选出最小的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
  分为三步:
  ①、从待排序序列中,找到关键字最小的元素
  ②、如果最小元素不是待排序序列的第一个元素,将其和第一个元素互换
  ③、从余下的 N - 1 个元素中,找出关键字最小的元素,重复(1)、(2)步,直到排序结束

 for(int i = 0 ; i < array.length-1 ; i++){
            int min = i;
            //每轮需要比较的次数
            for(int j = i+1 ; j < array.length ; j++){
                if(array[j]<array[min]){
                    min = j;//记录目前能找到的最小值元素的下标
                }
            }
            //将找到的最小值和i位置所在的值进行交换
            if(i != min){
                int temp = array[i];
                array[i] = array[min];
                array[min] = temp;
            }

3、插入排序
  直接插入排序基本思想是每一步将一个待排序的记录,插入到前面已经排好序的有序序列中去,直到插完所有元素为止。
  插入排序还分为直接插入排序、二分插入排序、链表插入排序、希尔排序等等,这里我们只是以直接插入排序讲解,后面讲高级排序的时候会将其他的。

     int j;
        //从下标为1的元素开始选择合适的位置插入,因为下标为0的只有一个元素,默认是有序的
        for(int i = 1 ; i < array.length ; i++){
            int tmp = array[i];//记录要插入的数据
            j = i;
            while(j > 0 && tmp < array[j-1]){//从已经排序的序列最右边的开始比较,找到比其小的数
                array[j] = array[j-1];//向后挪动
                j--;
            }
            array[j] = tmp;//存在比其小的数,插入
        }
        return array;
    }

Java数据结构和算法(四)——栈

栈作为一种数据结构,是一种只能在一端进行插入和删除操作的特殊线性表,栈也称为后进先出表。

//压入数据
        top=-1;    
    public void push(int value){
        if(top < maxSize-1){
            array[++top] = value;
        }
    }

这个栈是用数组实现的,内部定义了一个数组,一个表示最大容量的值以及一个指向栈顶元素的top变量
3、增强功能版栈
  对于上面出现的问题,第一个能自动扩容,第二个能存储各种不同类型的数据,解决办法如下:(第三个在讲链表的时候在介绍)
  这个模拟的栈在JDK源码中,大家可以参考 Stack 类的实现。
4、利用栈实现字符串逆序
我们可以将一个字符串分隔为单个的字符,然后将字符一个一个push()进栈,在一个一个pop()出栈就是逆序显示了。
char[] cha = str.toCharArray();
5、利用栈判断分隔符是否匹配

Java数据结构和算法(五)——队列

队列(queue)是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。
  队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出(FIFO—first in first out)线性表。
①、单向队列(Queue):只能在一端插入数据,另一端删除数据。
  ②、双向队列(Deque):每一端都可以进行插入数据和删除数据操作。
  这里我们还会介绍一种队列——优先级队列,优先级队列是比栈和队列更专用的数据结构,在优先级队列中,数据项按照关键字进行排序,关键字最小(或者最大)的数据项往往在队列的最前面,而数据项在插入的时候都会插入到合适的位置以确保队列的有序。
3、双端队列
  双端队列就是一个两端都是结尾或者开头的队列, 队列的每一端都可以进行插入数据项和移除数据项,这些方法可以叫做:
  insertRight()、insertLeft()、removeLeft()、removeRight()
  如果严格禁止调用insertLeft()和removeLeft()(或禁用右端操作),那么双端队列的功能就和前面讲的栈功能一样。
  如果严格禁止调用insertLeft()和removeRight(或相反的另一对方法),那么双端队列的功能就和单向队列一样了。
4、优先级队列
  优先级队列(priority queue)是比栈和队列更专用的数据结构,在优先级队列中,数据项按照关键字进行排序,关键字最小(或者最大)的数据项往往在队列的最前面,而数据项在插入的时候都会插入到合适的位置以确保队列的有序。
  优先级队列 是0个或多个元素的集合,每个元素都有一个优先权,对优先级队列执行的操作有:
  (1)查找
  (2)插入一个新元素
  (3)删除

//插入数据
    public void insert(int value){
        int j;
        if(nItems == 0){
            priQueArray[nItems++] = value;
        }else{
            j = nItems -1;
            //选择的排序方法是插入排序,按照从大到小的顺序排列,越小的越在队列的顶端
            while(j >=0 && value > priQueArray[j]){
                priQueArray[j+1] = priQueArray[j];
                j--;
            }
            priQueArray[j+1] = value;
            nItems++;
        }
    }

insert() 方法,先检查队列中是否有数据项,如果没有,则直接插入到下标为0的单元里,否则,从数组顶部开始比较,找到比插入值小的位置进行插入,并把 nItems 加1.
Java数据结构和算法(六)——前缀、中缀、后缀表达式 http://www.cnblogs.com/chensongxian/p/7059802.html
计算机必须要向前(从左到右)来读取操作数和操作符,等到读取足够的信息来执行一个运算时,找到两个操作数和一个操作符进行运算,有时候如果后面是更高级别的操作符或者括号时,就必须推迟运算,必须要解析到后面级别高的运算,然后回头来执行前面的运算
①、前缀表达式:操作符在操作数的前面,比如 ±543(从右到左)
   ②、中缀表达式:操作符在操作数的中间,这也是人类最容易识别的算术表达式 3+4-5
  ③、后缀表达式:操作符在操作数的后面,比如 34+5-(从左到右)
对于这个问题,转换的规则如下:
 在这里插入图片描述
堆排序的基本思路:
  a.将无需序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆;
  b.将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端;
  c.重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序
堆排序是一种选择排序,整体主要由构建初始堆+交换堆顶元素和末尾元素并重建堆两部分组成。其中构建初始堆经推导复杂度为O(n),在交换并重建堆的过程中,需交换n-1次,而重建堆的过程中,根据完全二叉树的性质,[log2(n-1),log2(n-2)…1]逐步递减,近似为nlogn。所以堆排序时间复杂度一般认为就是O(nlogn)级。

部分参考:https://www.cnblogs.com/ysocean/p/7911910.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值