JavaScript基础排序算法详解:冒泡、选择与插入排序实现及效率对比
本文深入解析JavaScript中的三种基础排序算法:冒泡排序、选择排序和插入排序。通过封装数组操作类,详细展示了各算法的代码实现与执行逻辑,并对比了它们的运行效率。文章指出插入排序在三种算法中速度最快,适合初学者理解排序原理与JavaScript编程实践。
数组测试平台构建
本文通过具体实例介绍了JavaScript中基本排序算法的定义及其效率对比,供读者参考学习。
JavaScript数据结构与算法系列:基本排序算法(冒泡、选择、插入)及效率比较
一、数组测试平台构建
为了调用不同的排序算法,我们需要封装一个包含常规数组操作的函数库,例如插入新数据、显示数组内容以及交换数组元素等功能。
function CArray(numElements) {
this.dataStore = [];
this.pos = 0;//是一个索引值,默认为0,从第一个开始
this.numElements = numElements;//是保存所有的数组元素
this.insert = insert;//向数组中插入一个元素的方法
this.toString = toString;//显示数组中所有元素
this.clear = clear;//清空数组数据
this.setData = setData;//生成了存储在数组中的随机数字
this.swap = swap;//交换数组中两个元素的位置
this.bubbleSort = bubbleSort;
/*将传入的数组,存储在datastore中*/
for (var i = 0; i < numElements.length; ++i) {
this.dataStore[i] = numElements[i];
}
}
function setData() {
for (var i = 0; i < this.numElements; ++i) {
this.dataStore[i] = Math.floor(Math.random() *
(this.numElements+1));
}
}
function clear() {
for (var i = 0; i < this.dataStore.length; ++i) {
this.dataStore[i] = 0;
}
}
function insert(element) {
this.dataStore[this.pos++] = element;
}
function toString() {
var retstr = "";
for (var i = 0; i < this.dataStore.length; ++i) {
retstr += this.dataStore[i] + " ";
if (i > 0 && i % 10 == 0) {
retstr += "\n";
}
}
return retstr;
}
function swap(arr, index1, index2) {
var temp = arr[index1];
arr[index1] = arr[index2];
arr[index2] = temp;
}
//测试生成一组数组数据(随机数)
var numElements = 100;
var myNums = new CArray(numElements);
myNums.setData();
console.log(myNums.toString());
17 94 81 80 25 24 73 76 24 35 81 63 81 59 4 76 30 47 73 98 18 54 36 53 47 22 60 88 41 66 24 73 94 40 45 72 74 14 61 92 48 36 12 42 11 12 82 24 84 60 1 17 98 63 36 84 13 18 50 89 26 98 1 6 54 52 69 6 52 98 14 79 28 19 69 76 99 97 100 10 7 24 54 81 73 18 21 45 73 66 30 28 56 54 21 88 31 20 86 48
冒泡排序算法解析
二、冒泡排序算法解析
首先介绍冒泡排序,这是所有排序算法中效率较低的一种,但其实现逻辑最为简单直观。
该算法得名于排序过程中数据值如同气泡般从数组一端向另一端漂浮移动的现象。
若将一组数字按升序排列,较大的数值会逐渐“浮”向数组右侧,而较小的数值则“沉”向左侧。
这种现象源于算法多次遍历数组,比较相邻的两个数据,当左侧值大于右侧值时执行互换操作。
JS代码如下:
function CArray(numElements) {
this.dataStore = [];
this.pos = 0;//是一个索引值,默认为0,从第一个开始
this.numElements = numElements;//是保存所有的数组元素
this.insert = insert;//向数组中插入一个元素的方法
this.toString = toString;//显示数组中所有元素
this.clear = clear;//清空数组数据
this.setData = setData;//生成了存储在数组中的随机数字
this.swap = swap;//交换数组中两个元素的位置
this.bubbleSort = bubbleSort;//冒泡算法
/*将传入的数组,存储在datastore中*/
for (var i = 0; i < numElements.length; ++i) {
this.dataStore[i] = numElements[i];
}
}
function setData() {
for (var i = 0; i < this.numElements; ++i) {
this.dataStore[i] = Math.floor(Math.random() *
(this.numElements+1));
}
}
function clear() {
for (var i = 0; i < this.dataStore.length; ++i) {
this.dataStore[i] = 0;
}
}
function insert(element) {
this.dataStore[this.pos++] = element;
}
function toString() {
var retstr = "";
for (var i = 0; i < this.dataStore.length; ++i) {
retstr += this.dataStore[i] + " ";
if (i > 0 && i % 10 == 0) {
retstr += "\n";
}
}
return retstr;
}
function swap(arr, index1, index2) {
var temp = arr[index1];
arr[index1] = arr[index2];
arr[index2] = temp;
}
function bubbleSort() {
var numElements = this.dataStore.length;
for (var outer = numElements; outer >= 2; --outer) {
for (var inner = 0; inner <= outer-1; ++inner) {
if (this.dataStore[inner] > this.dataStore[inner+1]) {
swap(this.dataStore, inner, inner+1);
}
}
console.log("outer为" + outer + ": " + this.toString());
}
}
//测试冒泡排序算法
var numElements = [2,4,1,3];
var myNums = new CArray(numElements);
console.log("原来的数组:"+myNums.toString());
myNums.bubbleSort();
console.log("排序后的数组:"+myNums.toString());
对冒泡算法代码的分析如下:
假设初始数组为 [2,4,1,3];
1. 当外层循环变量outer为4时
1. 内层循环inner为0,对应值2,inner+1为1,对应值4,不满足交换条件,不交换。 2. inner为1,对应值4,inner+1为2,对应值1,满足交换条件,数组变为[2,1,4,3] 3. inner为2,对应值4,inner+1为3,对应值3,满足交换条件,数组变为[2,1,3,4] 4. inner为3,对应值4,inner+1为4,超出范围,不交换。
2. 当外层循环变量outer为3时
1. inner为0,对应值2,inner+1为1,对应值1,满足交换条件,数组变为[1,2,3,4] 2. inner为1,对应值2,inner+1为2,对应值3,不满足交换条件,不交换。 3. inner为2,对应值3,inner+1为3,对应值4,不满足交换条件,不交换。
后续循环均不再满足交换条件,至此完成排序。这就是冒泡排序的完整过程。
选择排序算法解析
三、选择排序算法解析
选择排序从数组起始位置开始,将第一个元素与其他所有元素进行比较。
遍历完所有元素后,最小值被放置到数组的第一个位置,随后算法从第二个位置继续执行。
该过程持续进行,直到处理到数组倒数第二个元素,此时所有数据完成排序。 选择排序依赖于嵌套循环结构。
外层循环从数组的第一个元素遍历至倒数第二个元素;
内层循环从第二个元素遍历至最后一个元素,查找比当前外层循环所指元素更小的值。
每次内层循环迭代结束后,数组中的最小值会被放置到正确的位置。
JS代码如下:
function CArray(numElements) {
this.dataStore = [];
this.pos = 0;//是一个索引值,默认为0,从第一个开始
this.numElements = numElements;//是保存所有的数组元素
this.insert = insert;//向数组中插入一个元素的方法
this.toString = toString;//显示数组中所有元素
this.clear = clear;//清空数组数据
this.setData = setData;//生成了存储在数组中的随机数字
this.swap = swap;//交换数组中两个元素的位置
this.selectionSort = selectionSort;//选择排序算法
/*将传入的数组,存储在datastore中*/
for (var i = 0; i < numElements.length; ++i) {
this.dataStore[i] = numElements[i];
}
}
function setData() {
for (var i = 0; i < this.numElements; ++i) {
this.dataStore[i] = Math.floor(Math.random() *
(this.numElements+1));
}
}
function clear() {
for (var i = 0; i < this.dataStore.length; ++i) {
this.dataStore[i] = 0;
}
}
function insert(element) {
this.dataStore[this.pos++] = element;
}
function toString() {
var retstr = "";
for (var i = 0; i < this.dataStore.length; ++i) {
retstr += this.dataStore[i] + " ";
if (i > 0 && i % 10 == 0) {
retstr += "\n";
}
}
return retstr;
}
function swap(arr, index1, index2) {
var temp = arr[index1];
arr[index1] = arr[index2];
arr[index2] = temp;
}
function selectionSort() {
var min, temp;
for (var outer = 0; outer <= this.dataStore.length-2; ++outer) {
min = outer;
for (var inner = outer + 1;inner <= this.dataStore.length-1; ++inner) {
if (this.dataStore[inner] < this.dataStore[min]) {
min = inner;
}
}
swap(this.dataStore, outer, min);
console.log("第"+outer +"次:"+myNums.toString());
}
}
//测试排序算法
var numElements = [2,4,1,3];
var myNums = new CArray(numElements);
console.log("原来的数组:"+myNums.toString());
myNums.selectionSort();
console.log("排序后的数组:"+myNums.toString());
原始数组:2 4 1 3 第0次迭代后:1 4 2 3 第1次迭代后:1 2 4 3 第2次迭代后:1 2 3 4 最终排序结果:1 2 3 4
插入排序算法解析
四、插入排序算法解析
插入排序包含两个循环结构。
外层循环逐个移动数组元素,内层循环则对外层循环选中的元素及其前一个元素进行比较。
如果外层循环选中的元素小于内层循环选中的元素,数组元素会向右移动,为外层循环中的当前元素腾出插入位置。
function CArray(numElements) {
this.dataStore = [];
this.pos = 0;//是一个索引值,默认为0,从第一个开始
this.numElements = numElements;//是保存所有的数组元素
this.insert = insert;//向数组中插入一个元素的方法
this.toString = toString;//显示数组中所有元素
this.clear = clear;//清空数组数据
this.setData = setData;//生成了存储在数组中的随机数字
this.swap = swap;//交换数组中两个元素的位置
this.insertionSort = insertionSort;//插入排序算法
/*将传入的数组,存储在datastore中*/
for (var i = 0; i < numElements.length; ++i) {
this.dataStore[i] = numElements[i];
}
}
function setData() {
for (var i = 0; i < this.numElements; ++i) {
this.dataStore[i] = Math.floor(Math.random() *
(this.numElements+1));
}
}
function clear() {
for (var i = 0; i < this.dataStore.length; ++i) {
this.dataStore[i] = 0;
}
}
function insert(element) {
this.dataStore[this.pos++] = element;
}
function toString() {
var retstr = "";
for (var i = 0; i < this.dataStore.length; ++i) {
retstr += this.dataStore[i] + " ";
if (i > 0 && i % 10 == 0) {
retstr += "\n";
}
}
return retstr;
}
function swap(arr, index1, index2) {
var temp = arr[index1];
arr[index1] = arr[index2];
arr[index2] = temp;
}
function insertionSort() {
var temp, inner;
//外循环将数组元素挨个移动
for (var outer = 1; outer <= this.dataStore.length-1; ++outer) {
temp = this.dataStore[outer];//外循环选中的元素temp
inner = outer;
//内循环对外循环中选中的元素temp与temp前面的元素一个个进行比较。
//如果外循环中选中的元素temp比内循环中选中的元素小,那么数组元素会向右移动,为外循环中的这个元素腾出位置
while (inner > 0 && (this.dataStore[inner-1] >= temp)) {
this.dataStore[inner] = this.dataStore[inner-1];
--inner;
}
this.dataStore[inner] = temp;
console.log("第"+outer+"次:"+myNums.toString());
}
}
//测试排序算法
var numElements = [9,1,8,6,2,3,5,4];
var myNums = new CArray(numElements);
console.log("原来的数组:"+myNums.toString());
myNums.insertionSort();
console.log("排序后的数组:"+myNums.toString());
原始数组:9 1 8 6 2 3 5 4 //首先比较1和它前面的9,9比1大,所以9向右移动一个位置,给1腾位置 第1次迭代后:1 9 8 6 2 3 5 4 //比较8和它前面的9,9比8大,所以9向右移动一个位置,给8腾位置 第2次迭代后:1 8 9 6 2 3 5 4 //比较6和它前面的8、9,8、9都比6大,所以8、9向右移动一个位置,给6腾位置 第3次迭代后:1 6 8 9 2 3 5 4 第4次迭代后:1 2 6 8 9 3 5 4 第5次迭代后:1 2 3 6 8 9 5 4 第6次迭代后:1 2 3 5 6 8 9 4 第7次迭代后:1 2 3 4 5 6 8 9 最终排序结果:1 2 3 4 5 6 8 9
基本排序算法的效率对比
五、基本排序算法的效率对比
function CArray(numElements) {
this.dataStore = [];
this.pos = 0;//是一个索引值,默认为0,从第一个开始
this.numElements = numElements;//是保存所有的数组元素
this.insert = insert;//向数组中插入一个元素的方法
this.toString = toString;//显示数组中所有元素
this.clear = clear;//清空数组数据
this.setData = setData;//生成了存储在数组中的随机数字
this.swap = swap;//交换数组中两个元素的位置
this.bubbleSort = bubbleSort;//冒泡排序算法
this.selectionSort = selectionSort;//选择排序算法
this.insertionSort = insertionSort;//插入排序算法
/*将传入的数组,存储在datastore中*/
for (var i = 0; i < numElements.length; ++i) {
this.dataStore[i] = numElements[i];
}
}
function setData() {
for (var i = 0; i < this.numElements; ++i) {
this.dataStore[i] = Math.floor(Math.random() *
(this.numElements+1));
}
}
function clear() {
for (var i = 0; i < this.dataStore.length; ++i) {
this.dataStore[i] = 0;
}
}
function insert(element) {
this.dataStore[this.pos++] = element;
}
function toString() {
var retstr = "";
for (var i = 0; i < this.dataStore.length; ++i) {
retstr += this.dataStore[i] + " ";
if (i > 0 && i % 10 == 0) {
retstr += "\n";
}
}
return retstr;
}
function swap(arr, index1, index2) {
var temp = arr[index1];
arr[index1] = arr[index2];
arr[index2] = temp;
}
function bubbleSort() {
var numElements = this.dataStore.length;
for (var outer = numElements; outer >= 2; --outer) {
for (var inner = 0; inner <= outer-1; ++inner) {
if (this.dataStore[inner] > this.dataStore[inner+1]) {
swap(this.dataStore, inner, inner+1);
}
}
// console.log("outer为" + outer + ": " + this.toString());
}
}
function selectionSort() {
var min, temp;
for (var outer = 0; outer <= this.dataStore.length-2; ++outer) {
min = outer;
for (var inner = outer + 1;inner <= this.dataStore.length-1; ++inner) {
if (this.dataStore[inner] < this.dataStore[min]) {
min = inner;
}
}
swap(this.dataStore, outer, min);
// console.log("第"+outer +"次:"+this.toString());
}
}
function insertionSort() {
var temp, inner;
//外循环将数组元素挨个移动
for (var outer = 1; outer <= this.dataStore.length-1; ++outer) {
temp = this.dataStore[outer];//外循环选中的元素
inner = outer;
//内循环则对外循环中选中的元素与它前面的那个元素进行比较。
//如果外循环中选中的元素比内循环中选中的元素小,那么数组元素会向右移动,为外循环中的这个元素腾出位置
while (inner > 0 && (this.dataStore[inner-1] >= temp)) {
this.dataStore[inner] = this.dataStore[inner-1];
--inner;
}
this.dataStore[inner] = temp;
// console.log("第"+outer+"次:"+this.toString());
}
}
/*测试冒泡、选择、插入算法的效率*/
var numElements = 10000;
var nums = new CArray(numElements);
nums.setData();
var start = new Date().getTime();
nums.bubbleSort();
var stop = new Date().getTime();
var elapsed = stop - start;
console.log("用冒泡算法,排序 " + numElements + " 个元素耗时 : " + elapsed + " milliseconds.");
start = new Date().getTime();
nums.selectionSort();
stop = new Date().getTime();
elapsed = stop - start;
console.log("用选择算法,排序 " + numElements + " 个元素耗时: " + elapsed + " milliseconds.");
start = new Date().getTime();
nums.insertionSort();
stop = new Date().getTime();
elapsed = stop - start;
console.log("用插入算法,排序 " + numElements + " 个元素耗时: " + elapsed + " milliseconds.");
运行结果展示:

测试表明,选择排序和插入排序的速度均优于冒泡排序,其中插入排序是这三种算法中执行最快的。
感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun测试上述代码的运行效果。
PS:这里再推荐一款关于排序的演示工具供参考:
在线动画演示插入/选择/冒泡/归并/希尔/快速排序算法过程工具: http://tools.jb51.net/aideddesign/paixu_ys
更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《JavaScript数学运算用法总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript数组操作技巧总结》、《JavaScript排序算法总结》、《JavaScript遍历算法与技巧总结》、《JavaScript查找算法技巧总结》及《JavaScript错误与调试技巧总结》
希望本文所述的算法解析对大家掌握JavaScript程序设计有所帮助。
JS处理含Emoji或中文的字符串转数组乱码问题
2026-11-05 16:12:28
JS怎么使用展开运算符合并对象
2026-11-05 14:42:18
ES6+环境下判断JS对象为空的简洁写法
2026-11-05 12:12:23
怎么通过replacer函数自定义JS中JSON的格式化输出
2026-11-05 11:19:44
JS正则表达式基础:字面量与RegExp构造函数的区别及常用元字符
2026-11-05 11:16:58
