数据结构和算法

 

冒泡排序

原理

依次比较相邻的两个值,如果后面的比前面的小,则将小的元素排到前面。依照这个规则进行多次并且递减的迭代,直到顺序正确。

时间复杂度,空间复杂度,稳定性

  • 平均时间复杂度O(n*n)
  • 最好情况O(n)
  • 最差情况O(n*n)
  • 空间复杂度O(1)
  • 稳定性:稳定
  • var examplearr=[8,94,15,88,55,76,21,39];

function sortarr(arr){

for(i=0;i<arr.length;i++){

for(j=0;j<arr.length-i;j++){

if(arr[j]>arr[j+1]){

var temp=arr[j];

arr[j]=arr[j+1];

arr[j+1]=temp;

}

}

}

return arr;

}

sortarr(examplearr);

  • console.log(examplearr);

 

(2).快速排序

原理:快速排序思想:先找到一个基准点(一般指数组的中部),然后数组被该基准点分为两部分,依次与该基准点数据比较,如果比它小,放左边;反之,放右边。
    左右分别用一个空数组去存储比较后的数据。最后递归执行上述操作,直到数组长度<=1;

时间复杂度O(logn),空间复杂度O(n)~O(n*n),稳定性好,常用

var str =[8,94,15,88,55,76,21,39];

var times=0;

var quickSort=function(arr){

    //如果数组长度小于等于1无需判断直接返回即可

    if(arr.length<=1){

        return arr;

    }

var midIndex=Math.floor(arr.length/2);//取基准点,舍弃小数 Math,floor 舍弃小数取整

    var midIndexVal=arr.splice(midIndex,1);//取基准点的值

    var left=[];//存放比基准点小的数组

    var right=[];//存放比基准点大的数组

    //遍历数组,进行判断分配

    for(var i=0;i<arr.length;i++){

        if(arr[i]<midIndexVal){

            left.push(arr[i]);//比基准点小的放在左边数组

        }

        else{

            right.push(arr[i]);//比基准点大的放在右边数组

        }

        console.log("第"+(++times)+"次排序后:"+arr);

    }

    //递归执行以上操作,对左右两个数组进行操作,直到数组长度为<=1;

    return quickSort(left).concat(midIndexVal,quickSort(right));//concat(参数) 用于数组之间的连接,

};

console.log(quickSort(str));


(3).hash表

Hash表是一种特殊的数据结构,它和数组,链表,二叉排序不同,它采用了函数映射的思想将记录的存储位置与记录的关键字关联起来,从而能够很快速地进行查找。

 

1.Hash表的设计思想:

张三 15812220074

李四 15812220075

王五 15812220076

对于一般的线性表,比如链表,如果要存储联系人信息:

 那么可能会设计一个结构体包含姓名,手机号码这些信息,然后把4个联系人的信息存到一张链表中,会从链表的头结点开始遍历,这种做法的时间复杂度为O(n)。即使采用二叉排序树进行存储,也最多为O(logn)。Hash表就能够达到这样的效果。Hash表采用一个映射函数 f : key —> address 将关键字映射到该记录在表中的存储位置。复杂度直接降到O(1)

Hash函数的设计

1)直接定址法

 取关键字或者关键字的某个线性函数为Hash地址,即address(key)=a*key+b;如知道学生的学号从2000开始,最大为4000,则可以将address(key)=key-2000作为Hash地址。

 

2)平方取中法

  对关键字进行平方运算,然后取结果的中间几位作为Hash地址。假如有以下关键字序列{421,423,436},平方之后的结果为{177241,178929,190096},那么可以取{72,89,00}作为Hash地址。

3)折叠法

  将关键字拆分成几部分,然后将这几部分组合在一起,以特定的方式进行转化形成Hash地址。假如知道图书的ISBN号为8903-241-23,可以将address(key)=89+03+24+12+3作为Hash地址。

4)除留取余法

  如果知道Hash表的最大长度为m,可以取不大于m的最大质数p,然后对关键字进行取余运算,address(key)=key%p。

  在这里p的选取非常关键,p选择的好的话,能够最大程度地减少冲突,p一般取不大于m的最大质数。

 即使再高效的散列键值生成函数也是有可能发生碰撞

1.开链法

 

当碰撞发生时,我们仍然希望将键存储到通过散列算法产生的索引位置上,但实际上,不可能将多份数据存储到一个数组单元中。开链法是指实现散列表的底层数组中,每个数组元素又是一个新的数据结构,比如另一个数组,这样就能存储多个键了。即使两个键散列后的值相等,依然被保存在同样的位置,只不过它们在第二层数组中的位置不一样罢了。

 

2.线性探测法

线性探测法属于一种更一般化的散列技术:开发寻址散列。当发生碰撞时,线性探测发检测散列表中的下一个位置是否为空。如果为空,就将数据存入该位置;如果不为空,则继续检查下一个位置,直到找到一个空的位置为止。该技术是基于这样一个事实:每个散列表都会有很多空的单元格,可以使用它们来存储数据。

采用线性探测法的时候,先给HashTable类初始化一个存储值的数组values = []; 存储键值使用table = [];

 

如果数组的大小是待存储数据个数的1.5倍,那么使用开链法;如果数组的大小是待存储的数据的2倍及两倍以上,那么使用线性探测法

 

posted @ 2019-04-16 14:50  鸡腿太小  阅读(149)  评论(0编辑  收藏  举报