首页 > 技术文章 > 数组与简单排序(冒泡,选择,插入)

xwzp 2017-09-12 15:05 原文

一.数组

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)。

推荐阅读