1. 使用本章讨论的所有算法对字符串数据而非数字数据进行排序,并比较不同算法的执行 时间。这两者的结果是否一致呢?
function CArray(numElements) { this.dataStore = []; this.pos = 0; this.numElements = numElements; this.insert = insert; this.toString = toString; this.clear = clear; this.setData = setData; this.swap = swap; /*for ( var i = 0; i < numElements; ++i ) { this.dataStore[i] = i; }*/for ( var i = 0; i < numElements; ++i ) { this.dataStore[i] = String.fromCharCode(65 + i % 26); }this.bubbleSort = bubbleSort;this.selectionSort = selectionSort;this.insertionSort = insertionSort;this.gaps = [5,3,1];this.shellsort = shellsort;this.shellsort1 = shellsort1;this.mergeSort = mergeSort; this.mergeArrays = mergeArrays;
}/*
function setData() { for ( var i = 0; i < this.numElements; ++i ) { this.dataStore[i] = Math.floor(Math.random() * (this.numElements + 1)); }
}
*/
function setData() { for ( var i = 0; i < this.numElements; ++i ) { this.dataStore[i] = String.fromCharCode(65 + Math.floor(Math.random() * 26)); }
} 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() { for ( var i = this.dataStore.length; i > 1; --i) { for ( var j = 0; j < i - 1; ++j ) { if (this.dataStore[j] > this.dataStore[j + 1]) { swap(this.dataStore, j, j + 1); } }//console.log(this.dataStore);}
}function selectionSort() { for (var i = 0; i < this.dataStore.length-1; ++i) { for (var j = i + 1; j < this.dataStore.length; ++j) { if (this.dataStore[j] < this.dataStore[i]) { swap(this.dataStore, i, j); } } //console.log(this.dataStore);}
}function insertionSort() { for (var i = 1; i < this.dataStore.length; ++i) { for (var j = i; j > 0; j--) { if (this.dataStore[j - 1] > this.dataStore[j]) {swap(this.dataStore, j, j - 1);}} //console.log(this.dataStore);}
}function shellsort() { for (var g = 0; g < this.gaps.length; ++g) { for (var i = this.gaps[g]; i < this.dataStore.length; ++i) { for (var j = i; j >= this.gaps[g] && this.dataStore[j-this.gaps[g]] > this.dataStore[j]; j -= this.gaps[g]) { swap(this.dataStore, j, j - this.gaps[g]);} //console.log(this.dataStore);} }
}function shellsort1() { var N = this.dataStore.length; var h = 1; while (h < N/3) { h = 3 * h + 1; } while (h >= 1) { for (var i = h; i < N; i++) { for (var j = i; j >= h && this.dataStore[j] < this.dataStore[j-h]; j -= h) { swap(this.dataStore, j, j-h); } //console.log(this.dataStore);} h = (h-1)/3; }
}function mergeArrays(arr,startLeft, stopLeft, startRight, stopRight) { var rightArr = arr.slice(startRight, stopRight + 1); var leftArr = arr.slice(startLeft, stopLeft + 1);rightArr.push(Infinity);leftArr.push(Infinity);var m = 0; var n = 0; for (var k = startLeft; k <= stopRight; ++k) { if (leftArr[m] <= rightArr[n]) { arr[k] = leftArr[m]; m++; } else { arr[k] = rightArr[n]; n++; } } //console.log("left array - ", leftArr); //console.log("right array - ", rightArr);
} function mergeSort() { if (this.dataStore.length < 2) { return; } var step = 1; while (step < this.dataStore.length) { var left = 0; var right = step; while (right + step <= this.dataStore.length) { mergeArrays(this.dataStore, left, left + step - 1, right, right + step - 1); left = right + step; right = left + step; } if (right < this.dataStore.length) { mergeArrays(this.dataStore, left, left + step - 1, right, this.dataStore.length - 1); } step *= 2; }
} function qSort(list) { if (list.length <= 1) { return list; } var lesser = []; var greater = []; var equal = [];var pivotIndex = Math.floor(list.length / 2);var pivot = list[pivotIndex]; for (var i = 0; i < list.length; i++) { if (i == pivotIndex) {continue;}if (list[i] < pivot) { lesser.push(list[i]); } else if (list[i] > pivot) { greater.push(list[i]); } else {equal.push(list[i]);}}return qSort(lesser).concat([pivot], equal, qSort(greater));
}function measureExecutionTime(sortFunction, context) {var startTime = performance.now();if (context instanceof CArray) {sortFunction.call(context);} else {context = sortFunction(context);}var endTime = performance.now();return endTime - startTime;
}var numElements = 30000;
var cArray = new CArray(numElements);
cArray.setData();
var algorithms = [{ name: 'Bubble Sort', func: cArray.bubbleSort, context: cArray },{ name: 'Selection Sort', func: cArray.selectionSort, context: cArray },{ name: 'Insertion Sort', func: cArray.insertionSort, context: cArray },{ name: 'Shell Sort', func: cArray.shellsort, context: cArray },{ name: 'Shell Sort 1', func: cArray.shellsort1, context: cArray },{ name: 'Merge Sort', func: cArray.mergeSort, context: cArray },{ name: 'Quick Sort', func: qSort, context: cArray.dataStore.slice() }
];
algorithms.forEach(algo => {var time = measureExecutionTime(algo.func, algo.context);console.log(`${algo.name}: ${time.toFixed(2)} ms`);
});//Bubble Sort: 3131.30 ms
//Selection Sort: 2211.20 ms
//Insertion Sort: 1556.70 ms
//Shell Sort: 2.30 ms
//Shell Sort 1: 2.30 ms
//Merge Sort: 18.80 ms
//Quick Sort: 5.60 ms
2. 创建一个包含 1000 个整数的有序数组。编写一个程序,用本章讨论的所有算法对这个 数组排序,分别记下它们的执行时间,并进行比较。如果对一个无序的数组进行排序结 果又会怎样?
function CArray(numElements) { this.dataStore = []; this.pos = 0; this.numElements = numElements; this.insert = insert; this.toString = toString; this.clear = clear; this.setData = setData; this.swap = swap; for ( var i = 0; i < numElements; ++i ) { this.dataStore[i] = i; }/*for ( var i = 0; i < numElements; ++i ) { this.dataStore[i] = String.fromCharCode(65 + i % 26); }*/this.bubbleSort = bubbleSort;this.selectionSort = selectionSort;this.insertionSort = insertionSort;this.gaps = [5,3,1];this.shellsort = shellsort;this.shellsort1 = shellsort1;this.mergeSort = mergeSort; this.mergeArrays = mergeArrays;
}function setData() { for ( var i = 0; i < this.numElements; ++i ) { this.dataStore[i] = Math.floor(Math.random() * (this.numElements + 1)); }
} /*
function setData() { for ( var i = 0; i < this.numElements; ++i ) { this.dataStore[i] = String.fromCharCode(65 + Math.floor(Math.random() * 26)); }
}
*/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() { for ( var i = this.dataStore.length; i > 1; --i) { for ( var j = 0; j < i - 1; ++j ) { if (this.dataStore[j] > this.dataStore[j + 1]) { swap(this.dataStore, j, j + 1); } }//console.log(this.dataStore);}
}function selectionSort() { for (var i = 0; i < this.dataStore.length-1; ++i) { for (var j = i + 1; j < this.dataStore.length; ++j) { if (this.dataStore[j] < this.dataStore[i]) { swap(this.dataStore, i, j); } } //console.log(this.dataStore);}
}function insertionSort() { for (var i = 1; i < this.dataStore.length; ++i) { for (var j = i; j > 0; j--) { if (this.dataStore[j - 1] > this.dataStore[j]) {swap(this.dataStore, j, j - 1);}} //console.log(this.dataStore);}
}function shellsort() { for (var g = 0; g < this.gaps.length; ++g) { for (var i = this.gaps[g]; i < this.dataStore.length; ++i) { for (var j = i; j >= this.gaps[g] && this.dataStore[j-this.gaps[g]] > this.dataStore[j]; j -= this.gaps[g]) { swap(this.dataStore, j, j - this.gaps[g]);} //console.log(this.dataStore);} }
}function shellsort1() { var N = this.dataStore.length; var h = 1; while (h < N/3) { h = 3 * h + 1; } while (h >= 1) { for (var i = h; i < N; i++) { for (var j = i; j >= h && this.dataStore[j] < this.dataStore[j-h]; j -= h) { swap(this.dataStore, j, j-h); } //console.log(this.dataStore);} h = (h-1)/3; }
}function mergeArrays(arr,startLeft, stopLeft, startRight, stopRight) { var rightArr = arr.slice(startRight, stopRight + 1); var leftArr = arr.slice(startLeft, stopLeft + 1);rightArr.push(Infinity);leftArr.push(Infinity);var m = 0; var n = 0; for (var k = startLeft; k <= stopRight; ++k) { if (leftArr[m] <= rightArr[n]) { arr[k] = leftArr[m]; m++; } else { arr[k] = rightArr[n]; n++; } } //console.log("left array - ", leftArr); //console.log("right array - ", rightArr);
} function mergeSort() { if (this.dataStore.length < 2) { return; } var step = 1; while (step < this.dataStore.length) { var left = 0; var right = step; while (right + step <= this.dataStore.length) { mergeArrays(this.dataStore, left, left + step - 1, right, right + step - 1); left = right + step; right = left + step; } if (right < this.dataStore.length) { mergeArrays(this.dataStore, left, left + step - 1, right, this.dataStore.length - 1); } step *= 2; }
} function qSort(list) { if (list.length <= 1) { return list; } var lesser = []; var greater = []; var equal = [];var pivotIndex = Math.floor(list.length / 2);var pivot = list[pivotIndex]; for (var i = 0; i < list.length; i++) { if (i == pivotIndex) {continue;}if (list[i] < pivot) { lesser.push(list[i]); } else if (list[i] > pivot) { greater.push(list[i]); } else {equal.push(list[i]);}}return qSort(lesser).concat([pivot], equal, qSort(greater));
}var numElements = 30000;
var orderedArray = new CArray(numElements);
var unorderedArray = new CArray(numElements);
unorderedArray.setData();
function testSortingAlgorithms(array, name) {console.log(`\n排序 ${name} 数组:`);var arrays = [{ name: '冒泡排序', method: 'bubbleSort' },{ name: '选择排序', method: 'selectionSort' },{ name: '插入排序', method: 'insertionSort' },{ name: '希尔排序(固定间隔)', method: 'shellsort' },{ name: '希尔排序(动态间隔)', method: 'shellsort1' },{ name: '归并排序', method: 'mergeSort' },{ name: '快速排序', method: 'qSort' }];arrays.forEach(({ name, method }) => {var startTime = performance.now();if (method === 'qSort') {array.dataStore = qSort(array.dataStore.slice());} else {array[method]();}var endTime = performance.now();console.log(`${name}: ${(endTime - startTime).toFixed(2)} 毫秒`);});
}
testSortingAlgorithms(orderedArray, '有序');
testSortingAlgorithms(unorderedArray, '无序');
//排序 有序 数组:
//冒泡排序: 939.90 毫秒
//选择排序: 318.00 毫秒
//插入排序: 828.70 毫秒
//希尔排序(固定间隔): 2.50 毫秒
//希尔排序(动态间隔): 1.90 毫秒
//归并排序: 12.20 毫秒
//快速排序: 14.20 毫秒
//
//排序 无序 数组:
//冒泡排序: 1374.60 毫秒
//选择排序: 306.50 毫秒
//插入排序: 811.00 毫秒
//希尔排序(固定间隔): 1.20 毫秒
//希尔排序(动态间隔): 2.30 毫秒
//归并排序: 8.60 毫秒
//快速排序: 14.10 毫秒
3. 创建一个包含 1000 个整数的倒序数组。编写一个程序,用本章讨论的所有算法对这个 数组排序,分别记下它们的执行时间,并进行比较。
function CArray(numElements) { this.dataStore = []; this.pos = 0; this.numElements = numElements; this.insert = insert; this.toString = toString; this.clear = clear; this.setData = setData; this.swap = swap; for ( var i = 0; i < numElements; ++i ) { this.dataStore[i] = i; }/*for ( var i = 0; i < numElements; ++i ) { this.dataStore[i] = String.fromCharCode(65 + i % 26); }*/this.bubbleSort = bubbleSort;this.selectionSort = selectionSort;this.insertionSort = insertionSort;this.gaps = [5,3,1];this.shellsort = shellsort;this.shellsort1 = shellsort1;this.mergeSort = mergeSort; this.mergeArrays = mergeArrays;
}function setData() { for ( var i = 0; i < this.numElements; ++i ) { this.dataStore[i] = Math.floor(Math.random() * (this.numElements + 1)); }
} /*
function setData() { for ( var i = 0; i < this.numElements; ++i ) { this.dataStore[i] = String.fromCharCode(65 + Math.floor(Math.random() * 26)); }
}
*/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() { for ( var i = this.dataStore.length; i > 1; --i) { for ( var j = 0; j < i - 1; ++j ) { if (this.dataStore[j] > this.dataStore[j + 1]) { swap(this.dataStore, j, j + 1); } }//console.log(this.dataStore);}
}function selectionSort() { for (var i = 0; i < this.dataStore.length-1; ++i) { for (var j = i + 1; j < this.dataStore.length; ++j) { if (this.dataStore[j] < this.dataStore[i]) { swap(this.dataStore, i, j); } } //console.log(this.dataStore);}
}function insertionSort() { for (var i = 1; i < this.dataStore.length; ++i) { for (var j = i; j > 0; j--) { if (this.dataStore[j - 1] > this.dataStore[j]) {swap(this.dataStore, j, j - 1);}} //console.log(this.dataStore);}
}function shellsort() { for (var g = 0; g < this.gaps.length; ++g) { for (var i = this.gaps[g]; i < this.dataStore.length; ++i) { for (var j = i; j >= this.gaps[g] && this.dataStore[j-this.gaps[g]] > this.dataStore[j]; j -= this.gaps[g]) { swap(this.dataStore, j, j - this.gaps[g]);} //console.log(this.dataStore);} }
}function shellsort1() { var N = this.dataStore.length; var h = 1; while (h < N/3) { h = 3 * h + 1; } while (h >= 1) { for (var i = h; i < N; i++) { for (var j = i; j >= h && this.dataStore[j] < this.dataStore[j-h]; j -= h) { swap(this.dataStore, j, j-h); } //console.log(this.dataStore);} h = (h-1)/3; }
}function mergeArrays(arr,startLeft, stopLeft, startRight, stopRight) { var rightArr = arr.slice(startRight, stopRight + 1); var leftArr = arr.slice(startLeft, stopLeft + 1);rightArr.push(Infinity);leftArr.push(Infinity);var m = 0; var n = 0; for (var k = startLeft; k <= stopRight; ++k) { if (leftArr[m] <= rightArr[n]) { arr[k] = leftArr[m]; m++; } else { arr[k] = rightArr[n]; n++; } } //console.log("left array - ", leftArr); //console.log("right array - ", rightArr);
} function mergeSort() { if (this.dataStore.length < 2) { return; } var step = 1; while (step < this.dataStore.length) { var left = 0; var right = step; while (right + step <= this.dataStore.length) { mergeArrays(this.dataStore, left, left + step - 1, right, right + step - 1); left = right + step; right = left + step; } if (right < this.dataStore.length) { mergeArrays(this.dataStore, left, left + step - 1, right, this.dataStore.length - 1); } step *= 2; }
} function qSort(list) { if (list.length <= 1) { return list; } var lesser = []; var greater = []; var equal = [];var pivotIndex = Math.floor(list.length / 2);var pivot = list[pivotIndex]; for (var i = 0; i < list.length; i++) { if (i == pivotIndex) {continue;}if (list[i] < pivot) { lesser.push(list[i]); } else if (list[i] > pivot) { greater.push(list[i]); } else {equal.push(list[i]);}}return qSort(lesser).concat([pivot], equal, qSort(greater));
}var numElements = 30000;
var reverseArray = new CArray(numElements);
function testSortingAlgorithms(array, name) {console.log(`\n排序 ${name} 数组:`);var arrays = [{ name: '冒泡排序', method: 'bubbleSort' },{ name: '选择排序', method: 'selectionSort' },{ name: '插入排序', method: 'insertionSort' },{ name: '希尔排序(固定间隔)', method: 'shellsort' },{ name: '希尔排序(动态间隔)', method: 'shellsort1' },{ name: '归并排序', method: 'mergeSort' },{ name: '快速排序', method: 'qSort' }];arrays.forEach(({ name, method }) => {var startTime = performance.now();if (method === 'qSort') {array.dataStore = qSort(array.dataStore.slice());} else {array[method]();}var endTime = performance.now();console.log(`${name}: ${(endTime - startTime).toFixed(2)} 毫秒`);});
}
testSortingAlgorithms(reverseArray, '倒序');
//排序 倒序 数组:
//冒泡排序: 939.10 毫秒
//选择排序: 314.90 毫秒
//插入排序: 775.60 毫秒
//希尔排序(固定间隔): 2.10 毫秒
//希尔排序(动态间隔): 1.70 毫秒
//归并排序: 10.70 毫秒
//快速排序: 14.10 毫秒
4. 创建一个包含 10 000 个随机整数的数组,使用快速排序和 JavaScript 内置的排序函数分 别对它进行排序,记录下它们的执行时间。这两种方法在执行时间上是否有区别?
function qSort(list) { if (list.length <= 1) { return list; } var lesser = []; var greater = []; var equal = [];var pivotIndex = Math.floor(list.length / 2);var pivot = list[pivotIndex]; for (var i = 0; i < list.length; i++) { if (i == pivotIndex) {continue;}if (list[i] < pivot) { lesser.push(list[i]); } else if (list[i] > pivot) { greater.push(list[i]); } else {equal.push(list[i]);}}return qSort(lesser).concat([pivot], equal, qSort(greater));
}function builtInSort(array) {return array.sort((a, b) => a - b);
}function createRandomArray(numElements) {var randomArray = [];for (var i = 0; i < numElements; i++) {randomArray.push(Math.floor(Math.random() * 1000000));}return randomArray;
}var numElements = 30000;
var randomArray = createRandomArray(numElements);function measureExecutionTime(sortFunction, array) {var startTime = performance.now();sortFunction(array);var endTime = performance.now();return endTime - startTime;
}var quickSortCopy = [...randomArray];
var quickSortTime = measureExecutionTime(qSort, quickSortCopy);
console.log(`Quick Sort: ${quickSortTime.toFixed(2)} ms`);
var builtInSortCopy = [...randomArray];
var builtInSortTime = measureExecutionTime(builtInSort, builtInSortCopy);
console.log(`Built-in Sort: ${builtInSortTime.toFixed(2)} ms`);//Quick Sort: 16.60 ms
//Built-in Sort: 9.20 ms