• 数组与简单排序(冒泡,选择,插入)


    一.数组

    1.数组的概念

    数组:数组(Array)是一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据

    线性表:就是数据排成一条线一样的结构,每个线性表上的数据最多只有前后两个方向。数组,链表,栈,队列等

    非线性表:数据之间不是简单的前后关系,如:二叉树,图,堆等

    连续的内存空间和相同的数据类型:正是因为两个要求,才使数组具有随机访问的能力。

    随机访问的实现:a[i]_address = base_address + i * data_type_size

    计算机想要随机访问数组中的元素的时候,通过上面的寻址公式,计算出元素的内存地址。其中base_address是数组的首地址,i是元素的下标,data_type_size是元素的大小

    2.数组的插入 删除

    数组为了保证内存的连续性,所以插入和删除都会导致数据的搬移,导致插入,删除操作的低效性。

    为了避免数据的迁移,在插入操作的时候,我们向k位置插入数据,同时将原来k位置的数据移到数组的末尾;删除操作的时候,不直接删除元素,将元素标记为删除,当数组的空间不足的时候,将所有被标记的元素的统一删除。这种操作很像jvm标记清除算法的思想。

    3.数组下标越界

    java本身会做下标越界检查:抛出异常。java.lang.ArrayIndexOutOfBoundsException

    4.容器和数组

    java将数组分装成容器;arraylist

    arraylist的优点:将很多数组操作的细节分装起来,最大的优点就是支持动态扩容 1.5倍。当然动态扩容是很耗时,如果我们知道数组的大小,直接初始化的时候指定好。

    arraylist不能存储基本类型,只能存储Integer,long等对象,涉及到封装与解封装,性能有所降低。

    一般工作中容器已经足够使用,只有在对性能要求比较高的时候,才需要考虑使用数组。

    5.数组下标为何从0开始

    从上面的寻址公式中可以看出,如果下标从1开始的话,cpu每次进行寻址的时候都要进行下标 - 1的操作,对于数组这种基础的数据结构,性能要做到最优。

    当然,还有很大的原因是历史缘故。

    6.有序数组和无序数组的比较

    1.有序数组要比无序数组在查找上更快,可以使用二分法查找
    2.有序数组在插入时较慢,有序数组需要找插入的位置
    3.有序数组和无序数组在删除时都比较慢,因为都需要进行补位(用后面的元素填补删除的空当)。

     7.数组的复杂度分析

    数组支持随机访问,随机访问的时间复杂度为O(1)

    数组的删除和插入操作的时间复杂度为O(n)

    二.冒泡排序

     1.冒泡排序的时间复杂度O(n^2)

    2.代码

     1 public static void sort(int[] arr){
     2         for(int i=arr.length-1;i>0;i--){
     3             for(int j=0;j<i;j++){
     4                 if(arr[j]>arr[j+1]){
     5                     int temp = arr[j];
     6                     arr[j] = arr[j+1];
     7                     arr[j+1] = temp;
     8                 }                
     9             }
    10         }
    11     }

    三.选择排序

    1.选择排序的时间复杂度O(n^2),操作的次数要比冒泡排序少

    2.代码

     1     public static void sort1(int[] arr){
     2         for(int i = 0;i<arr.length-1;i++){
     3             int min = i;
     4             for(int j = i+1;j<arr.length;j++){
     5                 if(arr[j]<arr[min]){
     6                     min = j;
     7                 }
     8             }
     9             if(i!=min){
    10                 int temp = arr[min];
    11                 arr[min] = arr[i];
    12                 arr[i] = temp;
    13             }            
    14         }
    15     }

    四.插入排序

    1.插入排序的算法时间复杂度为O(n^2)

    2.代码

     1     public static void sort2(int[] arr){
     2         int in,temp;
     3         for(int i = 1;i<arr.length;i++){
     4             temp = arr[i];
     5             in = i;
     6             while(in>0 && arr[in-1]>=temp){
     7                 arr[in] = arr[in-1];
     8                 --in;
     9             }
    10             arr[in] = temp;
    11         }
    12     }

    五.总结

    1.冒泡排序是效率最低,也是最简单的。

    2.选择排序虽然减少了交换的次数,但比较的次数仍然很大。

    3.插入排序是三种算法中应用最多的排序,当部分有序的时候,插入排序是个好的选择。

    4.这三种算法的时间复杂度都是O(n^2)。

  • 相关阅读:
    附上我的Github源码
    Java Automic包下的AtomicInteger
    思维题:四个小伙伴过桥问题
    TCP的三次握手过程?为什么会采用三次握手,若采用二次握手可以吗
    输入www.baidu.com会发生什么
    外网IP和内网IP区别
    Queue接口分析:add和offer区别,remove和poll方法到底啥区别
    手工创建一个线程池
    volatile关键字
    牛客网 买手串
  • 原文地址:https://www.cnblogs.com/xwzp/p/7506017.html
Copyright © 2020-2023  润新知