一、数组
来源:互联网 发布:windows经典桌面壁纸 编辑:程序博客网 时间:2024/06/02 05:29
数据结构是数据存储的抽象结构,而不是实际结构。例如以数组为抽象数据结构,在实际磁盘中存储的数据,并非是顺序存储的。数组有下标,如果知道一个数的下标,可以通过a[index]直接取出数据,因为它有一个指针指向磁盘的某一个位置。
一、操作
1. 插入
数组的插入总是将新的数据项放入下一个有空的地方。a[index]。所以无论数组的数据项有多大,插入的时间复杂度都是O(1)。
2. 查找
- 线程查找 与N成正比
查找有多种查找方式,如果数组是一个无序数组,通常查找一个值,都是线性查找,即从头开始遍历数组,直到找到这个值,查找过程结束。它的平均时间为:n/2。数据越大,查询耗时越大。 - 二分查找 与lg(N)成正比
例如1-100的数字中,查找33这个数,最少用几次
使用二分查找,最多只使用7次即可完成查询。当前,前提是数组是已经排好序的。与线性查找相比,速度快了很多。
因为每次都是折半,所以它的最差查找时间为:
3. 删除
删除某项数据后,当前数据末尾的数据项都要向前移动一个位置来填补它。所以,删除的时间复杂度是O(N)
二、数组的优缺点
优点
数组的优点就是插入速度快,逻辑简单易于理解。
缺点
- 如果是无序数组,查找时间慢
- 数组一旦被创建后,大小尺寸都是固定的,不方便扩展。
三、二分查找
/** * 二分查找 * * @param ints 被查找数组 * @param searchKey 被查找值 * @return 返回数组下标,如果没有,则抛异常NotFondException */public int find(int[] ints, int searchKey) throws Exception { int start = 0; int end = ints.length - 1; int executionCount = 0; while (start < end) { executionCount++; int index = (start + end) / 2; if (ints[index] < searchKey) { start = index + 1; } else if (ints[index] > searchKey) { end = index - 1; } else { System.out.println("共查找" + executionCount + "次"); return index; } } throw new Exception("not found " + searchKey); }
四、数组的排序
- 冒泡排序
- 选择排序
- 插入排序
- 归并排序
- 希尔排序
- 快速排序
1. 冒泡排序
思想
从左到右依次比较相邻的两个数,每次比较将大的数放在后边,最终结果是,最大的数将在末位,这表示第一回排序结束。
去除最后一个数,重复上面的步骤,这一回又得到最大的一个数在最后。
依次类推,循环n次后,将得到最终的结果。
还有一种思想,即始终都拿需要排序的子数组的第一个去与后面的进行比较,把最小的放在第一位,这样比较的结果是前面先排好序。与上面思维相反。一般写代码都是这样的。
图例
Java代码
public static void sort(int[] array) { if (array.length > 1) { for (int i = 0; i < array.length; i++) { for (int j = i; j < array.length; j++) { if (array[i] > array[j]) { int temp = array[i]; array[i] = array[j]; array[j] = temp; } } } } } public static void sort2(int[] array) { if (array.length > 1) { for (int i = array.length - 1; i >= 0; i--) { for (int j = 0; j < i; j++) { if (array[i] < array[j]) { int temp = array[i]; array[i] = array[j]; array[j] = temp; } } } } }
效率
冒泡排序的效率是非常低的。时间复杂度一般O(1)表示最好,O(
2. 选择排序
思想
选择排序的思想是在冒泡的基础上进行了一次改进。冒泡排序每比较一次差不多都需要交换位置,而选择排序则一趟比较,只需要交换一次。它的思维是将最小的进行标记,然后和待排序数组的第一个值进行交换。
图解
Java代码
public void sort(int[] array) { for (int i = 0; i < array.length; i++) { int index = i; int temp = array[index]; for (int j = i; j < array.length; j++) { if (array[index] > array[j]) { index = j; } } array[i] = array[index]; array[index] = temp; } }
效率
选择排序和冒泡相比,虽然时间复杂度并没有变化,只是它的复制交换次数变少了。如果是一个对象排序,复制一个对象耗时如果比较大的话,选择排序将是更好的选择。
3. 插入排序
思想
插入排序的思想是,一个数组,前面有k个值是已经排好序的,然后从k+1开始,依次从后向前比较,插入到已排序的数组的合适位置。
图解
实现
public static void sort(int[] array) { for (int i = 1; i < array.length; i++) { int index = i - 1; while (index >= 0 && array[index] >= array[index + 1]) { int temp = array[index]; array[index] = array[index + 1]; array[index + 1] = temp; index--; } } }
效率
插入排序的最差情况是,每次插入时,都将插入到第一位,比较次数依次为:1+2+……+(n-1)。和冒泡排序相等。这是插入排序的最差情况。最好情况是0,即已经是有序了。所以,插入排序的平均值是最差的一半。也就是
综上可以看出,插入排序速度理论上是冒泡排序的一倍。以上三种方式插入排序是简单排序里面最快的一种,而且也易于理解。
4. 归并排序
思想
面试的时候,面试官问了我一个问题,两个有序的数组,合并后继续保持有序,如何实现。当时想都没想,回答合并再排序。面试官继续问,还有没有更好的方式。在这之前并没有归并的概念(也许大学是学过,不过我确实不记得归并的思想),于是我简单想了一下,一次合并的时候,就让它有序。
例如:int[] a = {1,3,5,7,9};int[] b = {0,2,4,6,8};合并到c数组时:
1与0比较,0小,0先放入c,接着b数组指针向后移动一位,继续比较,1比2小,1放入c中,a数组指针向后移动一位。依次类推,就能完成。
归并排序的思想是根据此为基础,将一个数组拆分成一半,再拆分……依次合并。最终得到一个有序数组。
图解
实现
效率
5. 希尔排序
思想
图解
实现
效率
6. 快速排序
思想
图解
实现
效率
- 数组(一)
- 数组一
- 数组(一)
- 一、数组
- 数组(一维数组)
- 数组---一维数组
- 数组一 数组概述 (c#)
- 数组(一维数组)
- java数组--一维数组
- 一维数组,字符数组
- 一维数组、二维数组
- 一维数组&三维数组
- Java数组 一维数组,二维数组
- array 数组 一维数组 二维数组
- 一维数组、数组排序、字符数组
- Javascript - 数组 一维数组 二维数组
- 数组心得(一)
- 面试题(一)数组
- [BFS] HDU 3533
- Java消息队列任务的平滑关闭
- 基于Camshift道路检测(改),基于划定框的匹配
- unity 断点续传
- 例题6-21 uva506 System Dependencies 模拟
- 一、数组
- centos7—raid
- HDU-2019(数列有序!)(逗号运算符和逻辑运算符)
- android资源
- Spring 注解概览
- 「Deep Learning」Spatial Transformer Networks
- intellij的高效使用快捷键
- Python中画图时候的线类型
- 小白入门JAVA,记录一下成长过程