算法入门
算法是什么?
百度上说:能够对一定规范的输入,在有限时间内获得所要求的输出。
换成简单的说法,就是指解决问题的方法。
解决什么问题?
- 比如一堆毫无规律的数据,我们怎么让它们排成有规律的数组,这个时候可以设计一个函数,使它按照规则去排列,达到排序的目的。这就是排序算法。
- 再比如,你要确定一个数在队列里的位置,可以使用算法达到查找的目的,如二分查找等...
介绍一下简单的算法
假设所有排序方法都在升序排序下
1、冒泡排序
思路:比较相邻的两个元素,如果前一个比后一个大,则交换位置。
function bubbleSort(arr) {
var len = arr.length;
for (var i = 0; i < len; i++) {
for (var j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j+1]) { //相邻元素两两对比
var temp = arr[j+1]; //元素交换
arr[j+1] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}
2、快速排序(Quick Sort)
思路:选择一个值,小于它的放在左边,大于它的放在右边,递归使用。
/* splice(index):向数组添加/删除元素
push():向数组末添加元素
concat():连接数组
*/
function quickSort(arr) {
var len = arr.length;
var pivotIndex = Math.floor(len / 2);
var pivot = arr.splice(pivotIndex, 1)[0];//选择出的点,每次递归都在变化
var left = [], right = [];
if(len <= 1){ //最后所有元素通过这个判断来确认位置,停止递归
return arr;
}
for(var i =0; i < len; i++){
if(arr[i] < piovt){
left.push(arr[i]);
}else{
right.push(arr[i]);
}
}
}
/*思考过选择的点(pivot)有什么要求?答案是没有,唯一的要求是这个点存在。*/
3、选择排序
思路:从所有元素中选出最小的,放在左边第一个,第二次选出剩下的元素中最小的,放在第二个。依次重复。
function selectionSort(arr) {
var len = arr.length;
var minIndex, temp;
for (var i = 0; i < len - 1; i++) {
minIndex = i;
for (var j = i + 1; j < len; j++) {
if (arr[j] < arr[minIndex]) { //寻找最小的数
minIndex = j; //将最小数的索引保存
}
}
temp = arr[i];
arr[i] = arr[minIndex];//选择出的最小元素,放在这个位置
arr[minIndex] = temp;
}
return arr;
}
4、插入排序
思路:先设定数组里已经存在一个元素了,即第一个元素,下一个元素在数组中找位置插入,依次到最后。
function insertionSort(arr) {
var len = arr.length;
var preIndex, current;//current指要插入的元素,现在在给它找位置
for (var i = 1; i < len; i++) {
preIndex = i - 1;
current = arr[i];//先将current放在第i个位置
while(preIndex >= 0 && arr[preIndex] > current) {
arr[preIndex+1] = arr[preIndex];//current之后的元素往后挪一挪
preIndex--;
}
arr[preIndex+1] = current;//current放在比它小的元素的后一位
}
return arr;
}
5、归并排序(Merge Sort)
思路:
- 归并排序是一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。
- 但实际过程是一边分解一边归并,前半部分分先排好序,后半部分再拍好,最后整个归并为一个完整的序列
/*
push()向数组的末尾添加一个或更多的元素
shift()删除并返回数组的第一个元素
*/
function mergeSort(arr) { //采用自上而下的递归方法
var len = arr.length;
if(len < 2) {
return arr;
}
var middle = Math.floor(len / 2),
left = arr.slice(0, middle),
right = arr.slice(middle);
return merge(mergeSort(left), mergeSort(right));
}
function merge(left, right)
{
var result = [];
while (left.length>0 && right.length>0) {
if (left[0] <= right[0]) {
result.push(left.shift());
} else {
result.push(right.shift());
}
}
while (left.length)
result.push(left.shift());
while (right.length)
result.push(right.shift());
return result;
console.log(result);
}
6、希尔排序
思路:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序。
这个不会暂时。。。
function shellSort(arr) {
var len = arr.length,temp, gap = 1;
while(gap < len/3) { //动态定义间隔序列
gap =gap*3+1;
}
for (gap; gap> 0; gap = Math.floor(gap/3)) {
for (var i = gap; i < len; i++) {
temp = arr[i];
for (var j = i-gap; j > 0 && arr[j]> temp; j-=gap) {
arr[j+gap] = arr[j];
}
arr[j+gap] = temp;
}
}
return arr;
}
二分查找
注意:二分查找适用于有序的顺序表,
基本的思路是:
- 首先将给定的关键字dest与表data的中间位置的元素进行比较。
- 如果相等,则查找成功,如果不相等,则查找的元素一定在表的前半部分或者后半部分。
- 继续缩小范围到前半部分或者后半部分再进行同样的查找,直到找到为止,或者查完之后仍然没有找到元素。
//递归方法:
function binarySearch01(data, dest, start, end){
var end = end|| data.length - 1,
start = start || 0,
m = Math.floor((start + end) / 2);
if(data[m] == dest){
return m;
}
if(dest < data[m]){
return binarySearch01(data, dest, 0, m - 1);
}else{
return binarySearch01(data, dest, m + 1, end);
}
return false;
}
//非递归方法
function binarySearch02(data, dest){
var h = data.length - 1,
l = 0;
while(l < h){
var m = Math.floor((h + l) / 2);
if(data[m] == dest){
return m;
}
if(dest > data[m]){
l = m + 1;
}else{
h = m - 1;
}
}
}