2022-02-24——js排序算法

2.24早,没事干,先自学一会

关于之前说过的创建对象:

第一种方式:

var person = new Object();

person.name = "孙悟空";

person.age = 18;

console.log(person);

第二种方式:

var person = {

    name: "孙悟空",

    age: 18

};

console.log(person);

这里引用的话就用对象.属性名这样的格式来写


obj数据加上基本数据类型,一共6种,这里梳理一下所有的数据类型:

基本数据类型

JavaScript中的变量可能包含两种不同数据类型的值:基本数据类型和引用数据类型。

JavaScript中一共有5种基本数据类型:String、Number、 Boolean、Undefined、Null

基本数据类型的值是无法修改的,是不可变的。

基本数据类型的比较是值的比较,也就是只要两个变量的值相等,我们就认为这两个变量相等。

引用数据类型

引用类型的值是保存在内存中的对象。

当一个变量是一个对象时,实际上变量中保存的并不是对象本身,而是对象的引用。当从一个变量向另一个变量复制引用类型的值时,会将对象的引用复制到变量中,并不是创建一个新的对象。这时,两个变量指向的是同一个对象。因此,改变其中一个变量会影响另一个


ok,完了就是今天最重要的内容,排序算法!!!!!!!!!!!

排序分为两大类

比较排序,时间复杂度为O(nlogn) ~ O(n^2),主要有:冒泡排序,选择排序,插入排序,归并排序,堆排序,快速排序

非比较排序,时间复杂度可以达到O(n),主要有:计数排序,基数排序,桶排序等

排序的定义

对一序列对象根据某个关键字进行排序。

稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面;

不稳定:如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面;

内排序:所有排序操作都在内存中完成;

外排序:由于数据太大,因此把数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行;

时间复杂度:一个算法执行所耗费的时间。

空间复杂度:运行完一个程序所需内存的大小。


n: 数据规模

k: “桶”的个数

In-place: 占用常数内存,不占用额外内存

Out-place: 占用额外内存

1、冒泡排序(Bubble Sort)

冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

1.比较相邻的元素。如果第一个比第二个大,就交换它们两个;

2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;

3.针对所有的元素重复以上的步骤,除了最后一个;

4.重复步骤1~3,直到排序完成。

 var arr = [20,63,50,40,10]

        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;

                    }

                }

            }

        console.log(arr);


2、选择排序(Selection Sort)

表现最稳定的排序算法之一,因为无论什么数据进去都是O(n²)的时间复杂度,所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。理论上讲,选择排序可能也是平时排序一般人想到的最多的排序方法了吧。

选择排序(Selection-sort)是一种简单直观的排序算法。它的工作原理:

1.在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,

2.再从剩余未排序元素中继续寻找最小(大)元素,

3.放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

var arr = [20,63,50,40,10];

        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;

        }

        console.log(arr);


3、插入排序(Insertion Sort)

插入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

一般来说,插入排序都采用in-place在数组上实现。具体算法描述如下:

1.从第一个元素开始,该元素可以认为已经被排序;

2.取出下一个元素,在已经排序的元素序列中从后向前扫描;

3.如果该元素(已排序)大于新元素,将该元素移到下一位置;

4.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;

5.将新元素插入到该位置后;

6.重复步骤2~5。

        var arr3 = [63,20,10,15,30];

        var len = arr3.length;

        var preIndex, current;

        for (var i = 1; i < len; i++) {

            preIndex = i - 1;

            current = arr3[i];                                  //创立一个值用来保存需要插入的值

            while(preIndex >= 0 && arr3[preIndex] > current) {  //用插入值与前值比较,若前者大于后者进入排序

                arr3[preIndex+1] = arr3[preIndex];              //该处相当于将前者向后移动一位,给插入值留出“空位”

                preIndex--;  

                // console.log(arr3)

            }  

            arr3[preIndex+1] = current;                         //若前者数值小于插入值时,跳出循环,将插入值插进“空位”

            // console.log(arr3)

        }


 4、归并排序(Merge Sort)

和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是O(n log n)的时间复杂度。代价是需要额外的内存空间。

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序是一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。

1.把长度为n的输入序列分成两个长度为n/2的子序列;

2.对这两个子序列分别采用归并排序;

3.将两个排序好的子序列合并成一个最终的排序序列。

该方法需要使用函数,所以这里暂且记一下,学完函数后回来补充。


5、快速排序(Quick Sort)

快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

1.从数列中挑出一个元素,称为 “基准”(pivot);

2.重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;

3.递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序

6、计数排序(Counting Sort)

计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。 作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。

计数排序(Counting sort)是一种稳定的排序算法。计数排序使用一个额外的数组C,其中第i个元素是待排序数组A中值等于i的元素的个数。然后根据数组C来将A中的元素排到正确的位置。它只能对整数进行排序。

1.找出待排序的数组中最大和最小的元素;

2.统计数组中每个值为i的元素出现的次数,存入数组C的第i项;

3.对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加);

4.反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1。

  var bucket =new Array(maxValue+1),

        sortedIndex = 0;

        arrLen = arr.length,

        bucketLen = maxValue + 1;

    for (var i = 0; i < arrLen; i++) {

        if (!bucket[arr[i]]) {

            bucket[arr[i]] = 0;

        }

        bucket[arr[i]]++;

    }

    for (var j = 0; j < bucketLen; j++) {

        while(bucket[j] > 0) {

            arr[sortedIndex++] = j;

            bucket[j]--;

        }

    }

这里记录一个大佬的帖子https://blog.csdn.net/lpfasd123/article/details/81199885?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-2.pc_relevant_aa&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-2.pc_relevant_aa&utm_relevant_index=2

作者是CSDN博主「lpfasd123」

我基本上都是看他的才看懂,该文中多出也是摘他的

最后放一张我自己看着都想笑的图,是我实在不理解算法时随手画的,这件事也证明了我实在不适合画画。。。


你可能感兴趣的:(2022-02-24——js排序算法)