1,插入排序
插入排序就是在已经有序的序列中,插入元素,使得插入后的整个序列依然是有序的。
1.1 ,插入排序的实现
执行流程
- 在执行过程中,插入排序会讲序分为两部分:头部是已经排好的序列,尾部是带排序的序列
- 从头开始扫描每一位元素:每当扫描到一个元素,就将它插入到头部合适的位置,使得头部数据依然保持有序
代码实现
for (int begain = 1; begain < array.length; begain++) {
//保存扫面元素的位置
int cur = begain;
//当cur==0时,进行下一个扫描
while (cur > 0 && cmp(cur, cur - 1) < 0) {
//交换两个元素
swap(cur, cur - 1);
cur --;
}
}
1.2,插入排序-优化
思路:将 交换 改为 挪动
- 先将待插入的元素备份
- 头部有序数据中比待插入的元素大,都朝尾部方向挪动1个位置
- 将待插入元素放到最终的合适位置
代码实现
for (int begain = 1; begain < array.length; begain++) {
//记录遍历位置
int cur = begain;
//备份插入的元素
T v = array[cur];
//当cur==0时,进入下一个扫描
while (cur > 0 && cmp(v,array[cur - 1]) < 0) {
//元素向后挪动
array[cur] = array[cur - 1];
cur --;
}
//在cur位置插入元素
array[cur] = v;
}
2,二分搜索
- 如果是无序数组,需要从第0个位置开始遍历搜索。平均时间复杂度为:O(n)
- 如果是有序数组,可以使用二分搜索,最坏时间复杂度:O(logn)
思路
- 假设在[begain,end)范围内搜索某个元素V,mid == (begain + end) / 2
- 如果v < m, 去[begain, mid)范围内二分搜索
- 如果v > m, 去[mid + 1, end)范围内二分搜索
- 如果v == m,直接返回mid
搜索实例
搜索10:
- mid = (0 + 7)/ 2 = 3,取出8和10比较,8小于10所以取右边
- 然后算出右边的mid = (3+7)/ 2 = 5。12比10大,继续二分查找
- 最后在4的位置命中
同理搜索3,最后begain == end == 1,没有找到,失败。
代码实现
public static int search(int[] array,int v) {
//如果array不存在,就return
if (array == null || array.length == 0) return -1;
//设置起始位置
int begain = 0;
//设置末尾位置
int end = array.length;
//进行遍历
while (begain < end) {
//取出中间位置
int mid = (begain + end) >> 1;
if (v < array[mid]) {
//中间位置索引变为end
end = mid
} else if (v > array[mid]) {
//中间位置加1的索引,变为begain
begain = mid + 1;
} else {
//没有找到就返回,最后的中间索引
return mid;
}
}
reutrn -1;
}
3,插入排序-二分搜索优化
- 在元素 v 的插入过程中,可以先二分搜索出合适的插入位置,然后再将元素 v 插入
- 要求二分搜索返回的插入位置:第一个大于v的元素位置
例如:
如果 v 是 5,返回索引 2
如果 v 是 1,返回索引 0
如果 v 是 15,返回索引 7
如果 v 是8,返回索引 5
思路
- 假设在[begain, end)范围内搜索某个元素 v ,mid == (begain + end)/ 2
- 如果 v < m , 去[begian,mid)范围内二分搜索
- 如果 v >= m, 去[mid + 1,end)范围内二分搜索
实现
//插入方法实现,seource:遍历的当前索引位置。dest:要插入的索引的位置
private void insert(int source, int dest) {
//备份当前元素
T v = array[source];
//source的索引位置大于dest的位置,进行挪动
for (int i = source; i > dest; i-- ) {
array[i] = array[i - 1];
}
array[dest] = v;
}
//二分搜索,找到插入位置对应的索引
private int search(int index) {
int begain = 0;
int end = index;
while (begain < end) {
int mid = (begian + end) >> 1;
if (cmp(index, mid) < 0) {
end = mid;
} else {
begain = mid + 1;
}
}
return begain;
}
//调用实现
for (int i = 1; i < array.length; i++) {
insert(i, search(i));
}