JavaScript数据结构与算法总结五——排序和查找(冒泡排序 选择排序 插入排序 快速排序 堆排序 顺序查找 二分查找 插值查找)

排序

冒泡排序

冒泡排序比较所有相邻的两个项,如果第一个比第二个大,则交换它们。元素项向上移动至正确的顺序,就好像气泡升至表面一样,冒泡排序因此得名。

//一维数组冒泡排序,从大到小
        let testArray = [77, 41, 31, 43, 11, 33, 21];
        for (let i = 0; i < testArray.length - 1; i++) {
            for (let j = 0; j < testArray.length - 1; j++) {
                if (testArray[j] > testArray[j + 1]) {
                	//冒泡,交换相邻数据元素
                    let t = testArray[i];
                    testArray[i] = testArray[i + 1];
                    testArray[i + 1] = t;
                }
            }
        }
        document.write(testArray);

如果从内循环减去外循环中已跑过的轮数,就可以避免内循环中所有不必要的比较.

        //一维数组改进冒泡排序,从大到小
        let testArray = [77, 41, 31, 43, 11, 33, 21];
        for (let i = 0; i < testArray.length - 1; i++) {
            for (let j = 0; j < testArray.length - 1 - i; j++) {
                if (testArray[j] > testArray[j + 1]) {
                    let t = testArray[i];
                    testArray[i] = testArray[i + 1];
                    testArray[i + 1] = t;
                }
            }
        }
        document.write(testArray);

选择排序

选择排序算法是一种原址比较排序算法。选择排序大致的思路是找到数据结构中的最小值并
将其放置在第一位,接着找到第二小的值并将其放在第二位,以此类推。

		//一维数组选择排序,从小到大
		let testArray = [77, 41, 31, 43, 11, 33, 21];
        let indexMin;

		//交换数据元素
        function swap(array,i,j){
            let t = array[i];
            array[i]=array[j];
            array[j]=t;
        }
        
        for (let i = 0; i < testArray.length - 1; i++) {
           indexMin = i;
           //选择未排序的元素中最小的元素
            for (let j = i; j < testArray.length; j++) {
                if (testArray[i] > testArray[j])
                  indexMin = j;  
            }
            if (i !== indexMin) {
                swap(testArray, i, indexMin);
            }
        }
        document.write(testArray);

插入排序

每次确定一个数据元素的位置,将该数据元素插入的该数据元素下标之前已经排好序的子序列的正确位置上。

  1. 从选定元素之前的子序列中查找出当前元素应该插入的位置
  2. 把选定位置后的元素后移,将待插入元素复制到该位置
		//一维数组直接插入排序,从小到大
        let testArray = [77, 41, 31, 43, 11, 33, 21];
        let temp,i,j;
        for (i = 1; i < testArray.length; i++) {
        	//如果当前元素比前面的元素小,则遍历前面的元素,把当前元素插入到正确的位置,待插入位置至当前元素初始位置前一个元素后移一位
            if(testArray[i]<testArray[i-1]){
                temp=testArray[i];
                //如果当前选择的元素比遍历的元素小则停止循环
                for(j=i-1;temp<testArray[j];--j){
                    testArray[j+1]=testArray[j];
                }
                testArray[j+1]=temp;
            }
        }
        document.write(testArray);

排序小型数组时,此算法比选择排序和冒泡排序性能要好。

快速排序

快速排序也许是最常用的排序算法了。它的复杂度为 O(nlog(n)),且性能通常比其他复杂度
为 O(nlog(n))的排序算法要好。

  1. 首先,从数组中选择一个值作为主元(pivot),主元可以任意选择。
  2. 创建两个指针(引用),左边一个指向数组第一个值,右边一个指向数组最后一个值。移动左指针直到我们找到一个比主元大的值,接着,移动右指针直到找到一个比主元小的值,然后交换它们,重复这个过程,直到左指针超过了右指针。这个过程将使得比主元小的值都排在主元之前,而比主元大的值都排在主元之后。这一步叫作划分(partition)操作。
  3. 接着,算法对划分后的小数组(较主元小的值组成的子数组,以及较主元大的值组成的子数组)重复之前的两个步骤,直至数组已完全排序。
		//一维数组快速排序,从小到大
        var testArray = [77, 41, 31, 43, 11, 33, 21];
        //递归
        function quickSort(arr, left, right) {
            if (left < right) {
                var pivotpos = partition(arr, left, right);
                quickSort(arr, left, pivotpos - 1);
                quickSort(arr, pivotpos + 1, right);
            }
            return arr;
        }
        //划分
        function partition(arr, left, right) {
            let pivot = left,index = pivot;
            for (let i = index; i <= right; i++) {
                if (arr[i] < arr[pivot]) {
                    swap(arr, i, index);
                    index++;
                }
            }
            swap(arr, pivot, index - 1);
            return index;
        }
        //交换
        function swap(array, i, j) {
            let t = array[i];
            array[i] = array[j];
            array[j] = t;
        }
        //输入数组,参与排序的起始位置和终止位置
        testArray = quickSort(testArray, 0, testArray.length - 1);
        document.write(testArray);

堆排序

  1. 用数组创建一个最大堆用作源数据。
  2. 在创建最大堆后,最大的值会被存储在堆的第一个位置。我们要将它替换为堆的最后一个值,将堆的大小减 1。
  3. 最后,我们将堆的根节点下移并重复步骤 2 直到堆的大小为 1。

我们用最大堆得到一个升序排列的数组(从最小到最大)。如果我们想要这个数组按降序排列,可以用最小堆代替。

        let testArray = [77, 41, 31, 43, 11, 33, 21];
        function heapSort(array) {
            let heapSize = array.length;
            buildMaxHeap(array); // 步骤 1 
            while (heapSize > 1) {
                swap(array, 0, --heapSize); // 步骤 2 
                heapify(array, 0, heapSize); // 步骤 3 
            }
            return array;
        }
        function buildMaxHeap(array) {
            for (let i = Math.floor(array.length / 2); i >= 0; i -= 1) {
                heapify(array, i, array.length);
                //document.write(testArray);
            }
            return array;
        }
        function heapify(arr, index, length) {
            var left = 2 * index + 1,
                right = 2 * index + 2,
                largest = index;
            if (left < length && arr[left] > arr[largest]) {
                largest = left;
            }
            if (right < length && arr[right] > arr[largest]) { 
                largest = right;
            }
            if (largest !== index) {
                swap(arr, index, largest);
                heapify(arr, largest, length, );
            }
        }
        function swap(arr, i, j) {
            var temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
        testArray = heapSort(testArray);
        document.write(testArray);

查找

顺序

顺序或线性查找是最基本的查找算法。它的机制是,将每一个数据结构中的元素和我们要找
的元素做比较。顺序搜索是最低效的一种查找算法。

		//一维数组顺序查找
        var testArray = [77, 41, 31, 43, 11, 33, 21];
        var key = 31;//查找关键字
        function seqSearch(arr,e){
            for(let i=0;i<arr.length;i++){
                if(arr[i]===e){
                    return i+1;
                }
            }
            return 0;
        }
        var index = seqSearch(testArray,key);
        if(index){
            document.write(key,"是第",index,"个元素");
        }else{
            document.write("查找失败");
        }

二分

二分查找又称折半查找,仅适用于有序的顺序表

		//一维数组二分查找
        var testArray = [77, 41, 31, 43, 11, 33, 21];
        let key = 31;
        function compare(a, b) {
            if (a < b) {
                return -1;
            }
            if (a > b) {
                return 1;
            }
            return 0;
        }

        function binarySearch(arr, e) {
            var left = 0, right = arr.length - 1, mid;
            while (left <= right) {
                mid = (left + right) / 2;
                if (arr[mid] === e) {
                    return mid + 1;
                } else if (arr[mid] > e) {
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
            }
            return 0;
        }

        //sort 方法在对数组做排序时,把元素默认成字符串进行相互比较,我们要传入自己写的比较行数。
        //排序
        testArray.sort(compare);
        document.write(testArray,"<br>");
        var index = binarySearch(testArray, key);
        if (index) {
            document.write(key, "是第", index, "个元素");
        } else {
            document.write("查找失败");
        }

插值

插值查找:根据查找关键字与查找表中最大最小记录关键字比较后的查找方法。插值查找基于二分查找,将查找点的选择改进为自适应选择,提高查找效率。
将二分查找的点改进为 mid = left+(e-arr[left])/(arr[right]-arr[left])*(right-left);
时间复杂度:O(log₂(log₂n))
应用:对于表长较大,而关键字分布又比较均匀的查找表来说,插值查找算法的平均性能比折半查找要好的多

		//一维数组插值查找
		var testArray = [77, 41, 31, 43, 11, 33, 21];
        let key = 43;
        function compare(a, b) {
            if (a < b) {
                return -1;
            }
            if (a > b) {
                return 1;
            }
            return 0;
        }

        function insertSearch(arr,e){
            var left = 0, right = arr.length - 1;
            while (left <= right) {
                var mid = left+(e-arr[left])/(arr[right]-arr[left])*(right-left);
                mid = Math.round(mid);
                if (arr[mid] === e) {
                    return mid + 1;
                } else if (arr[mid] > e) {
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
            }
            return 0;
        }

        testArray.sort(compare);
        document.write(testArray, "<br>");
        var index = insertSearch(testArray, key);
        if (index) {
            document.write(key, "是第", index, "个元素");
        } else {
            document.write("查找失败");
        }
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤影墨客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值