栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

对数据结构和算法的总结和思考(二)--简单排序算法

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

对数据结构和算法的总结和思考(二)--简单排序算法

冒泡排序

提起简单排序就不得不先提冒泡排序,为何,简单。只有简单的方法才有可能成为最优秀的方法,无疑,冒泡排序已经具备了简单的潜质。冒泡排序的实现原理是循环然后挨个比较相邻元素,不废话,直接上代码:

先附上一个swap.js的代码:

function swap(arr, i, j) {
    let temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

module.exports = swap;

基本实现

let swap = require('./swap.js');
function bubble(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]) {
  swap(arr, j, j + 1);
     } 
 }
    }

    return arr;
}

let arr = [7,11, 4,2, 3, 75, 63, 2, 9,1, 32, 3, 75, 6, 23, 9,1, 34, 14, 10];

console.log(bubble(arr))

这就是最简单的冒泡排序,但是显然不够,如果待排序的数组为顺序结构,这个排序方法会做很多无用功,下面是一次优化的代码:

let swap = require('./swap.js');
function bubble(arr) {
    let hasSwap = true;//标识符,区分是否有待交换的数据。
    for (let i = 0; i < arr.length && hasSwap; i ++) {
 hasSwap = false
 for (let j = 0; j < arr.length - 1 - i; j ++ ) {
     if (arr[j] > arr[j + 1]) {
  swap(arr, j, j + 1);
  hasSwap = true;
     } 
 }
    }

    return arr;
}

let arr = [7,11, 4,2, 3, 75, 63, 2, 9,1, 32, 3, 75, 6, 23, 9,1, 34, 14, 10];

console.log(bubble(arr))

经过一次优化,已经能够处理整个数组有序的情况了,但是,是否可以继续优化呢?可以的,例如每次排序之后数组最后的部分都是大元素,我们是否可以给定一个标识位置的变量用来控制数组已经排序到了哪里,下面是具体实现:

et count = 0;
function bubble(arr) {
    let flag = arr.length;
    let swapPos; //标识排序位置。
    for (let i = 0; i < arr.length; i ++) {
 swapPos = 0;
 for (let j = 0; j < flag - 1; j ++ ) {
     if (arr[j] > arr[j + 1]) {
  swap(arr, j, j + 1);
  swapPos = j + 1;
     } 
 }
 flag = swapPos;
    }

    return arr;
}

let arr = [7,11, 4,2, 3, 75, 63, 2, 9,1, 32, 3, 75, 6, 23, 9,1, 34, 14, 10];

console.log(bubble(arr));

经过两次优化后的冒泡排序,表现比基本的已经好了很多。

简单选择排序

简单选择排序的原理是先选出最大或最小值,然后选出次大或次小值,简单选择排序是移动元素次数最少的排序方式。
const swap = require('./swap.js');

let count = 0;
function select(arr) {
    for (let i = 0; i < arr.length - 1; i ++) {
 min = i;
 for (let j = i + 1; j < arr.length; j ++) {
     count ++;
     if (arr[j] < arr[min]) {
  min = j;//此处找出最小值的index
     }
 }
 if (min !== i) {
     swap(arr, i, min);
 }
    }
    return arr;
}

let arr = [];
for (let i = 0; i < 100; i ++) {
    arr.push(parseInt(Math.random() * 100));
}
console.log(select(arr));
console.log(count);

这个就不单独讲解优化了,主要代码简单,只要注意 min = j;//此处找出最小值的index 这一行,不要直接交换元素就行了。

简单插入排序

插入排序的原理就和打扑克牌一样,你先摸了一张牌,然后再摸一张,这张牌和第一张比较下,就知道放到哪里了。然后再摸第n张,这一张和前面n-1张比较下就知道这张放哪里了。

下面是代码实现:

let swap = require('./swap.js');
let count = 0;
function insert(arr) {
    for (let i = 1; i < arr.length; i ++) {
 let flag = arr[i],
     index = i,
     j = i - 1;
 if (arr[j] > arr[i]) {
     for (j; j >= 0 && arr[j] > flag; j --) {
  count ++;
  arr[j + 1] = arr[j];
  index = j;
     }
     arr[index] = flag;
 }

    }

    return arr;
}

let arr = [];
for (let i = 0; i < 100; i ++) {
    arr.push(parseInt(Math.random() * 100));
}
console.log(insert(arr));
console.log(count);

由于插入排序的原理是先让插入前的元素有序,所以在查找插入位置时,可以进行优化,可以采用比较高效的二分查找法,而不是顺序查找法的方式。下面是优化后的代码:

function binaryInsertionSort(arr, index) {
    console.time('二分插入排序耗时:')
    let count = index || 0;

    for (let i = 1; i < arr.length; i ++) {
 let left = 0, right = i - 1, middle;
 let key = arr[i];
 //二分查找法,找到待插入的位置
 while (left <= right) {
     middle = parseInt((left + right) / 2);
     if (key < arr[middle]) {
  right = middle - 1;
     } else {
  left = middle + 1;
     }
 }
 // 插入
 for (let j = i - 1; j >= left; j --) {
     arr[j + 1] = arr[j];
 }
 arr[left] = key;
    }
    console.timeEnd('二分插入排序耗时:')
    return arr;
}

let sortArr = [];
for (let i = 0;i < 100; i ++) {
    sortArr.push(parseInt(Math.random() * 100));
}
console.log(binaryInsertionSort(sortArr));

以上就是三种简单排序算法,我想也是大家最喜欢,用得最顺手的算法。但是这三种简单算法在数据量较少时表现尚可,在数据量较多的时候并不高效,并且平均查找时间均在O(n^2)。如果不熟悉大O表示法的童鞋可以自行搜索,我这里就不展开讲了。以上就是这次分享的内容,thx。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/225722.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号