今天总结一下之前学习过的几种排序算法
1 选择排序
一次选择偶爱徐,可以讲某个区间里的最小值排列到该区域的第一位,具体的思路是:
- 找出该区域的最小值
- 将该值与该区域的第一个值进行交换
- 对下一个区域的数据重复1、2过程,直到排序完成
代码实现为:
function choseSort(arr) {
for (i = 0; i < len - 1; i++) {
var min = arr[i]; //将a][i]记作最小值
var index = i;
记录最小值的坐标值
for (j = i + 1; j < len; j++) {
if (arr[j] < min) {
index = j; //将最小值位置标记为index
min = arr[j]; //将小于min的arr[j]赋值给min
}
}
swap(arr, i, index); //将查找出的最小值赋值到啊[i]处
}
}
2 冒泡排序
一次冒泡排序可以将某个区域序列的最大值排序到该区域的最后一位,具体的方式是:
1.将第一位和第二位比较,如果前者比后者大则交换
2.将第二位和第三位进行比较,如果前者比后者大则交换
3.以此类推,直到比较到该区域的最后两位,重复上过程,直到序列排序完成
具体代码实现为:
function bubbleSort(arr) {
for (i = 0; i < len - 1; i++) { //i值记录循环轮数
var index = i;
for (j = i + 1; j < len; j++) { //j记录每次循环所要进行比较的次数
if (arr[j] < arr[index]) {
swap(arr, index, j);
}
index = j;
} //j循环 结束
} //i循环结束
}
3 插入排序
将序列分为两个部分,一部分是有序的,一部分是无序的,现在要做的是,就是不断的从无序的部分取出数据,加入到有序的部分,直到整个排序完成。
例如序列:[5,7,2,3,6]
1.分为有序和无序序列(5)(7,2,3,6)
2.不断的扩充有序序列 (5,7)(2,3,6)
3.不断的扩充有序序列 (2,5,7)(3,6)
4.不断的扩充有序序列 (2,3,5,7)(6)
5.不断的扩充有序序列 (2,3,5,6,7)
6.排序完成
具体代码实现为:
function insertSort(arr) {
for (i = 1; i < len; i++) {
if (arr[i] < arr[i - 1]) {
swap(arr, i, i - 1);
}
for (j = i - 1; j > 0; j--) { //将新插入的无序值在有序序列排序
if (arr[j] > arr[j - 1]) //如果新插入的无序值最大 直接跳出循环
break;
else
swap(arr, j, j - 1)
}
console.log(arr)
}
}
4 快速排序
选择一个数作为基准(比如最后一位)将整个序列排成两个部分,一部分比较小,另一部分比较大,基准数在中间,然后对剩余的序列做同样的事情,直至排列完成
例如:同样的数组[5,7,2,3,6,4]
1.选择6作为基准,排序成为(3,2)4(7,6,5)
2.对于(2,3),同样的思想排序得到(2,3)4(7,6,5)
3.对于(7,6,5),同样的思想排序得到(2,3)4(5,6,7)
直至排序完成
具体代码实现为:
function quickSort(arr) {
//定义一个待调用的快速排序
function _quicksort(arr, start, end) {
if (start > end || start > len - 1) return;
var low = start,
high = end;
var key = arr[end];
while (low < high) {
while (low < high && arr[low] <= key) low++; //左边的指针往右移动
arr[high] = arr[low];
while (low < high && arr[high] >= key) high--; //右边的指针往左移动
arr[low] = arr[high];
}
arr[low] = key; //将指针重合处 的值记作新的Key值
_quicksort(arr, start, low - 1); //key值左侧调用快速排序
_quicksort(arr, low + 1, end); //key值右侧调用快速排序
}
_quicksort(arr, 0, len - 1);
}
5 查询算法
使用普通的遍历即可实现
代码实现:
5.1 顺序查找
function inorderSearch(arr, targetnode) {
for (i = 0; i < len; i++) {
if (arr[i] == targetnode) {
return i;
}
}
return false;
}
5.1 二分查找(针对已经排序号的序列找到某个未知数)
如果一个序列是一个排序号的序列,则使用二分查找可以大大缩短查找事件,具体的思路是:
- 相等,则表示找到
- 要找的数据较大,则对后面的数据继续做同样的步骤
- 要找到数据较小,则对前面的数据继续同样的步骤
具体实现:
// 创建一个有序序列
var arry = new Array(1000);
for (i = 0; i < arry.length; i++) {
arry[i] = i + 1;
}
console.log(arry)
// 二分查找 查找的前提是序列已经是有序的
function binarySearch(arr, targetnode) {
var start = 0;
var count = 0;
var end = arr.length - 1;
while (start <= end) {
count++;
var mid = Math.floor((start + end) / 2)
if (targetnode > arr[mid]) {
start = mid + 1;
} else if (targetnode < arr[mid]) {
end = mid - 1;
} else if (targetnode == arr[mid]) {
console.log(count);
return mid;
}
}
return false;
}
5.1 插值查找
插值查找是二分法的进一步改进
如果序列不仅是排序号的序列,而且序列的步长大致相同,使用插值查找会更好的找到目标值。
插值查找基于如下假设:下标之间的距离比和数据之间的距离比大致相同,即:
(目标下标 - 最小下标)/(最大下标 - 最小下标)≈ (目标值 - 最小值)/(最大值 - 最小值),可以推算出:目标值 ≈ (目标值 - 最小值)/最大值 - 最小值)*(最大下标 - 最小下标) + 最小下标
这样就可以计算出大致的下标落点,后续的比较和二分查找一样