一.常见的查找方法:
1.顺序查找:从表中第一个(或最后一个)记录开始,逐个进行记录的关键字和给 定值比较,若某个记录的关键字和给定值相同,则查找成功;如果直到最后一个(或第一个)记录,关键字和给定值比较都不相等,则查找不成功。
var arr = [1,4,53,6,9,3]
function find(arr,num){
for (let i = 0; i < arr.length; i++) {
if (arr[i] == num) {
return i
}
}
return null
}
console.log(find(arr,3)); 顺序查找的时间复杂度为O(n)
2.二分法查找:前提是必须有序的,用给定值k先与中间结点的关键字比较,中间结点把线形表分成两个子表,若相等则查找成功;若不相等,再根据k与该中间结点关键字的比较结果确定下一步查找哪个子表
const arr1 = [1, 4, 5, 8, 12, 16, 18]
function foo1(arr, num) {
let leftIndex = 0
let rightIndex = arr.length - 1
while (leftIndex <= rightIndex) {
let mid = Math.floor((leftIndex + rightIndex) / 2)
if (num === arr[mid]) { // 找到返回mid
return mid
} else if (num > arr[mid]) { // 比中间值大,说明在 mid 到 rightIndex 之间;否则就在 mid 到 leftIndex 之间
leftIndex = mid + 1
} else {
rightIndex = mid - 1
}
}
return -1 // 没找到返回-1
}
console.log(foo1(arr1, 18)) 二分法查找时间复杂度O(logn)
3、二叉查找树:
若它的左子树不为空,则左子树上所有节点的值均小于根节点的值;
若它的右子树不为空,则右子树上所有节点的值均大于根节点的值;
它的左右子树也是二叉排序树。
//二叉排序树的查找
function treeSearch(target, root) {
if (root) {
if (target == root.value) {
return true;
} else if (target < root.value) {
return treeSearch(target, root.left);
} else {
return treeSearch(target, root.right);
}
} else {
return false;
}
}
4、斐波那契查找:前提是有序序列查找,斐波那契查找采用和二分查找相似的区间分割策略,都是通过不断的分割区间缩小搜索的范围。
过程:构建斐波那契数列;f(n) = f(n-1) + f(n-2)
计算数组长度对应的斐波那契数列元素个数;
对数组进行填充;
循环进行区间分割,查找中间值;
判断中间值和目标值的关系,确定更新策略;
function fibSearch(target, arr) {
//简易斐波那契数列
function fib(n) {
if (n <= 1) {
return 1;
} else {
return fib(n - 1) + fib(n - 2);
}
}
var low = 0;
//记录数组长度,后续会填充数组
const temp = arr.length - 1;
var k = 0;
var mid = 0;
while (fib(k) - 1 < arr.length) {
k++;
}
high = fib(k) - 1;
//将arr数组填充至fib(k)的长度
for (var i = temp; i < high; i++) {
arr.push(arr[temp]);
}
while (low <= high) {
mid = low + fib(k - 1) - 1;
if (arr[mid] < target) {
low = mid + 1;
k = k - 2;
} else if (arr[mid] > target) {
high = mid - 1;
k = k - 1;
} else {
return mid <= temp ? mid : temp;
}
}
return -1;
} 斐波那契查找时间复杂度O(logn)
二、常见的排序方法:
1.冒泡排序:对相邻的元素进⾏两两⽐较,顺序相反则进⾏交换,这样每⼀次会将最⼩或最⼤的元素“浮”到顶端,最终达到完全有序。
var arr = [2,5,6,7,8,9,3,1,4]
function paixu(arr){
if (!Array.isArray(arr) || arr.length <= 1) return arr;
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr.length-1-i; j++) {
if (arr[j] > arr[j+1]) {
let a = arr[j]
arr[j] = arr[j+1]
arr[j+1] = a
}
}
}
return arr
}
console.log(paixu(arr)); 平均时间复杂度O(n*n)
2.直接插⼊排序: 每⼀步将⼀个待排序的记录,插⼊到前⾯已经排好序的有序序列中去,直到插完所有元素为⽌。
function insertSort(arr) {
if (!Array.isArray(arr) || arr.length <= 1) return;
for (let i = 1; i < arr.length; i++) { // 循环从 1 开始,0 位置为默认的已排序的序列
let temp = arr[i]; // 保存当前需要排序的元素
let j = i - 1;
//在当前已排序序列中⽐较,如果⽐需要排序的元素⼤,就依次往后移动位置
while (j >= 0 && arr[j] > temp) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = temp; // 将找到的位置插⼊元素
}
return arr;
}
console.log(insertSort([1, 6, 3, 2, 5])); 平均时间复杂度O(n*n)
3.选择排序:为每⼀趟从待排序的数据元素中选择最⼩(或最⼤)的⼀个元素作为⾸元素,直到所有元素排完为⽌。
var arr = [2,1,3,4,9,6]
function selectSort(arr){
let min; //定义min,缓存当前区间最小值的索引
for (let i = 0; i < arr.length; i++) {
min = i //初始化min为当前区间第一个元素
for (let j = i; j < arr.length; j++) { //i、j分别定义当前区间的上下界
if (arr[min] > arr[j]) {
min =j
}
}
if (min != i) {//如果minIndex对应元素不是目前的头部元素,则交换两者
[arr[i],arr[min]]= [arr[min],arr[i]]
}
}
return arr
}
console.log(selectSort(arr)); 平均时间复杂度O(n*n)
4.归并排序:递归的将数组两两分开直到只包含⼀个元素,然后 将数组排序合并,最终合并为排序好的数组。
function mergeSort(arr) {
if (arr.length < 2) {
return arr;
}
const mid = Math.floor(arr.length / 2);
const left = mergeSort(arr.slice(0, mid));
const right = mergeSort(arr.slice(mid));
return merge(left, right);
}
function merge(left, right) {
let res = [];
let i = 0;
let j = 0;
while (i < left.length && j < right.length) {
if (left[i] < right[j]) {
res.push(left[i]);
i++;
} else {
res.push(right[j]);
j++;
}
}
if (i < left.length) {
res.push(...left.slice(i));
} else {
res.push(...right.slice(j));
}
return res;
}
// console.log(mergeSort([3, 6, 2, 4, 1])); 时间复杂度 nlog(n)
5.快速排序: 通过⼀趟排序将要排序的数据分割成独⽴的两部分,其中⼀部分的所有数据都⽐另外⼀部分的所有数据都要⼩
//快速排序
var arr= [0,2,1,8,4,5,9]
function quickSort(arr) {
if (arr.length <= 1) {
return arr;
}
var midIndex = Math.floor(arr.length / 2);
var mid = arr.splice(midIndex, 1)[0];
var left = [];
var right = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i] < mid) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return quickSort(left).concat([mid], quickSort(right));
};
console.log(quickSort(arr));