New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
排序 #22
Comments
选择排序function selectSort(array) {
var n = array.length;
for (var i = 0; i < n; i++) {
var minIndex = i; //保存当前最小数的索引
for (var j = i + 1; j < n; j++) { //每次只从i的后一个位置开始查找
if (array[j] < array[minIndex]) {
minIndex = j;
}
}
if (i !== minIndex) {
swap(array, i, minIndex)
}
}
} |
插入排序function insertSort2(array) {
var n = array.length
for (var i = 1; i < n; i++) { //[i,n-1]是无序区
var target = array[i];
if (target < array[i - 1]) { //减少无效的内部循环
var j = i;
while (j > 0 && array[j - 1] > target) {
array[j] = array[j - 1]; // 前面的覆盖后面的
j--;
}
array[j] = target; //放入坑位
}
}
} |
希尔排序function shellSort(array) {
//生成增量序列 3x+1 [1, 4, 13, 40, 121, 364, 1093, 3280, 9841]
var n = array.length,
gaps = [1],
gap = 1;
while (true) {
gap = gap * 3 + 1
if (gap >= n) { //不能大于数组长度
break
}
gaps.push(gap)
}
while (gap = gaps.pop()) {
//对每个子数组进行排序
for (var g = 0; g < gap; g++) {
//****************正常的插入排序***************
for (var i = g + gap; i < n; i += gap) {
var target = array[i]; //从无序区取元素
if (target < array[i - gap]) {
//无序区的元素比有序区的小
var j = i;
while (j > 0 && array[j - gap] > target) {
array[j] = array[j - gap]; //将前面的元素覆盖后面的
j -= gap;//不是-1而是-gap
}
array[j] = target;
}
}
//****************正常的插入排序***************
}
}
};
function shellSort2(array) {
//希尔序列 [1, 2, 4, 9, 19, 39, 78, 156, 312, 625, 1250, 2500, 5000]
var n = array.length,
gaps = [],
gap = n;
while (gap != 1) {
gap = gap >> 1; //相当于 Math.floor(n/2)
gaps.unshift(gap)
}
while (gap = gaps.pop()) {
//对每个子数组进行排序
for (var g = 0; g < gap; g++) {
//****************正常的插入排序***************
for (var i = g + gap; i < n; i += gap) {
var target = array[i]; //从无序区取元素
if (target < array[i - gap]) {
//无序区的元素比有序区的小
var j = i;
while (j > 0 && array[j - gap] > target) {
array[j] = array[j - gap]; //将前面的元素覆盖后面的
j -= gap;//不是-1而是-gap
}
array[j] = target;
}
}
//****************正常的插入排序***************
}
}
};
function getSedgewickSeq(n) {
var startup1 = 0, startup2 = 2, array = [];
for (var i = 0; i < n; i++) {
if (i % 2 == 0) {
array[i] = 9 * Math.pow(4, startup1) - 9 * Math.pow(2, startup1) + 1;
startup1++;
} else {
array[i] = Math.pow(4, startup2) - 3 * Math.pow(2, startup2) + 1;
startup2++;
}
if (array[i] >= n) {
break;
}
}
return array
}
function shellSort3(array) {
//生成增量序列 [1, 5, 19, 41, 109, 209, 505, 929, 2161, 3905, 8929, 16001]
var n = array.length,
gaps = getSedgewickSeq(n),
gap = 1;
while (gap = gaps.pop()) {
//对每个子数组进行排序
for (var g = 0; g < gap; g++) {
//****************正常的插入排序***************
for (var i = g + gap; i < n; i += gap) {
var target = array[i]; //从无序区取元素
if (target < array[i - gap]) {
//无序区的元素比有序区的小
var j = i;
while (j > 0 && array[j - gap] > target) {
array[j] = array[j - gap]; //将前面的元素覆盖后面的
j -= gap;//不是-1而是-gap
}
array[j] = target;
}
}
//****************正常的插入排序***************
}
}
}
test(shellSort)
test(shellSort2)
test(shellSort3) |
归并排序function mergeArray(a, b) {
//n, m分别为a,b的最后索引; i为a的索引,j为b的索引,k为c的索引
var n = a.length - 1, m = b.length - 1, i = 0, j = 0, k = 0, c = []
while (i <= n && j <= m) {
//先比较两个数组等长的部分,看谁的元素较小,谁就先进c数组
c[k++] = a[i] < b[j] ? a[i++] : b[j++];
}
//可能a数组长些,那么将a数组剩下的元素一古脑儿全部扔进去
while (i <= n) {
c[k++] = a[i++];
}
//也可能是b数组长些,那么b数组的剩下的元素扔进去
while (j <= m) {
c[k++] = b[j++];
}
return c
}
function mergeArrayByIndex(a, begin, end, begin2, end2) {
//n, m分别为a,b的最后索引; i为a的索引,j为b的索引,k为c的索引
var n = end, m = end2, i = begin, j = begin2, k = 0, c = []
while (i <= n && j <= m) {
//先比较两个数组等长的部分,看谁的元素较先,谁就先进c数组
c[k++] = a[i] < a[j] ? a[i++] : a[j++];
}
//可能a数组长些,那么将a数组剩下的元素一古脑儿全部扔进去
while (i <= n) {
c[k++] = a[i++];
}
//也可能是b数组长些,那么b数组的剩下的元素扔进去
while (j <= m) {
c[k++] = a[j++];
}
return c
}
function mergeSort(array, toMerge) {
//如果数组还可以分割,并且处于分割模式
if (array.length > 1 && toMerge !== true) {
var top = array;
var mid = array.length >> 1;
top.left = array.slice(0, mid)
top.right = array.slice(mid);
top.left.top = top
top.right.top = top;
// console.log(top.left, top.right, "分割")
mergeSort(top.left)
mergeSort(top.right)
//如果数组只剩下一个或者处于合并模式
} else if (array.length === 1 || toMerge) {
if (array.top && !array.merged) { //如果左边合并了右边,那么右边就不用再合并左边
var isLeft = array === array.top.left;
var neighbor = isLeft ? array.top.right : array.top.left;
if (neighbor.length === 1 || neighbor.sorted) {
var temp = mergeArray(array, neighbor)
neighbor.merged = true;//表明已经
// console.log(temp, "合并")
for (var i = 0, n = temp.length; i < n; i++) {
array.top[i] = temp[i]
}
array.top.sorted = true
mergeSort(array.top, true)
}
}
}
}
function mergeSortObject(array) {
function sort(obj, toMerge) {
//如果数组还可以分割,并且处于分割模式
var { array, begin, end } = obj;
var n = end - begin;
if (n !== 0 && toMerge !== true) {
var mid = begin + ((end - begin) >> 1);
obj.left = {
begin: begin,
end: mid,
array: array,
top: obj,
}
obj.right = {
begin: mid + 1,
end: end,
array: array,
top: obj,
}
sort(obj.left)
sort(obj.right)
//如果数组只剩下一个或者处于合并模式
} else if (n === 0 || toMerge) {
if (obj.top && !obj.merged) { //如果左边合并了右边,那么右边就不用再合并左边
var top = obj.top;
var isLeft = obj === top.left;
var neighbor = isLeft ? top.right : top.left;
if ((neighbor.end == neighbor.begin) || neighbor.sorted) {
var temp = mergeArrayByIndex(array, begin, end, neighbor.begin, neighbor.end)
neighbor.merged = true;//表明已经
var b = top.begin;
for (var i = 0, n = temp.length; i < n; i++) {
array[b + i] = temp[i]
}
top.sorted = true
sort(top, true)
}
}
}
}
sort({
array: array,
begin: 0,
end: array.length - 1
})
return array
}
function mergeSortObject2(array) {
function sort(obj, toMerge) {
//如果数组还可以分割,并且处于分割模式
var { array, begin, end } = obj;
var n = end - begin;
if (n !== 0 && toMerge !== true) {
var mid = begin + ((end - begin) >> 1);
obj.left = {
begin: begin,
end: mid,
array: array,
}
obj.right = {
begin: mid + 1,
end: end,
array: array,
}
sort(obj.left)
sort(obj.right)
var temp = mergeArrayByIndex(array, begin, mid, mid + 1, end)
for (var i = 0, n = temp.length; i < n; i++) {
array[begin + i] = temp[i]
}
}
}
sort({
array: array,
begin: 0,
end: array.length - 1
})
return array
}
function mergeSortSimple(array) {
//如果数组还可以分割,并且处于分割模式
function sort(array, begin, end) {
//如果数组还可以分割,并且处于分割模式
if (begin !== end) {
var mid = begin + ((end - begin) >> 1);
sort(array, begin, mid);
sort(array, mid + 1, end);
var temp = mergeArrayByIndex(array, begin, mid, mid + 1, end);
for (var i = 0, n = temp.length; i < n; i++) {
array[begin + i] = temp[i];
}
}
}
sort(array, 0, array.length - 1);
return array
}
function shellSort(array) {
//生成增量序列 3x+1 [1, 4, 13, 40, 121, 364, 1093, 3280, 9841]
var n = array.length,
gaps = [1],
gap = 1;
while (true) {
gap = gap * 3 + 1
if (gap >= n) { //不能大于数组长度
break
}
gaps.push(gap)
}
while (gap = gaps.pop()) {
//对每个子数组进行排序
for (var g = 0; g < gap; g++) {
//****************正常的插入排序***************
for (var i = g + gap; i < n; i += gap) {
var target = array[i]; //从无序区取元素
if (target < array[i - gap]) {
//无序区的元素比有序区的小
var j = i;
while (j > 0 && array[j - gap] > target) {
array[j] = array[j - gap]; //将前面的元素覆盖后面的
j -= gap;//不是-1而是-gap
}
array[j] = target;
}
}
//****************正常的插入排序***************
}
}
};
test(bubbleSort3)
test(shellSort)
test(mergeSort)
test(mergeSortObject)
test(mergeSortObject2)
test(mergeSortSimple) |
刚才我们是从上到下进行归产排序,我们的思路总是想着左边要合并右边。如果们一开始就把数组的每一个元素都当成一个微型数组,然后两两合并,再继而四四合并,一直它的长度靠近原数组长度。这样排序就完成了。 function mergeArray(a, first, mid, last, temp) {
var i = first, j = mid + 1;
var m = mid, n = last;
var k = 0;
while (i <= m && j <= n) {
if (a[i] <= a[j]) {
temp[k++] = a[i++];
} else {
temp[k++] = a[j++];
}
}
while (i <= m) {
temp[k++] = a[i++];
}
while (j <= n) {
temp[k++] = a[j++];
}
for (i = 0; i < k; i++) {
a[first + i] = temp[i];
}
}
function mergeSort(array) {// 进行两两归并
var n = array.length;
var temp = new Array(n)// 一次性的分配辅助空间
//定义微型数组的长度,初始为1
for (var sz = 1; sz < n; sz = sz + sz) {
//定义微型数组的索引low
for (var low = 0; low < n - sz; low += sz + sz) {
mergeArray(array, low, low + sz - 1,
Math.min(low + sz + sz - 1, n - 1), temp);
}
}
} |
三路快排快排是二路划分的算法。如果待排序列中重复元素过多,也会大大影响排序的性能。这时候,如果采用三路划分,则会很好的避免这个问题。 https://blog.csdn.net/lw_power/article/details/77986602 function quickSort3Ways(arr, left, right) {
if (left >= right) {
return;
}
var lt = left;
var gt = right;
var i = left + 1;
var pivot = arr[left];
while (i <= gt) {
if (arr[i] < pivot) {
swap(arr, i++, lt++);
} else if (arr[i] > pivot) {
swap(arr, i, gt--);
} else { // arr[i]==v
i++;
}
}
quickSort3Ways(arr, left, lt - 1);
quickSort3Ways(arr, gt + 1, right);
}
function quick(a) {
if (a.length > 0) {
quickSort3Ways(a, 0, a.length - 1);
}
}
//4 1 3 0 2 5 9 8 6 7
var array = [4, 1, 7, 6, 9, 2, 8, 0, 3, 5]
quick(array)
console.log(array) 双基准快速排序与上面的三路快排功率差不多,它也是用来改善数组重复元素够多的情况 //inspired by https://blog.csdn.net/limenglin0927/article/details/18077923
function quickSortDualPivot(array, left, right) {
if (right <= left) return;
var pivot1 = array[left];
var pivot2 = array[right];
if (pivot1 > pivot2) {
swap(array, left, right);
pivot1 = array[left];
pivot2 = array[right];
//sort(array, left, right);
} else if (pivot1 == pivot2) {
while (pivot1 == pivot2 && left < right) {
left++;
pivot1 = array[left];
}
}
var i = left + 1;
var lt = left + 1;
var gt = right - 1;
while (i <= gt) {
if (array[i] < pivot1) {
swap(array, i++, lt++);
} else if (pivot2 < array[i]) {
swap(array, i, gt--);
} else {
i++;
}
}
swap(array, left, --lt);
swap(array, right, ++gt);
quickSortDualPivot(array, left, lt - 1);
quickSortDualPivot(array, lt + 1, gt - 1);
quickSortDualPivot(array, gt + 1, right);
}
function quick(a) {
if (a.length > 0) {
quickSortDualPivot(a, 0, a.length - 1);
}
}
//4 1 3 0 2 5 9 8 6 7
var array = [4, 1, 1, 7, 6, 9, 5, 2, 8, 0, 3, 5]
quick(array)
console.log(array) |
最大组合数问题给一个非负整数数组,让它排序后合并后得到的数字最大,比如[3, 30, 34, 5, 9]排序成[9, 5, 34, 3, 30],得到的数9534330为最大。 思路:我们先比较相邻两个数,它们组合后的两个方式的大小, [3, 30, 34, 5, 9].
sort(function(a, b) {
var v1 = Number(a + "" + b)
var v2 = Number(b + "" + a);
var ret = v1 > v2 ? 1 : (v1 === v2 ? 0: -1)
return -1 * ret;
}) |
计数排序function countSort(arr) {
var max = arr[0], min = arr[0], n = arr.length;
for (var i = 0; i < n; i++) {
if (arr[i] > max) {
max = arr[i];
}
if (arr[i] < min) {
min = arr[i];
}
}
var size = max - min + 1;
var buckets = new Array(size).fill(0);
//遍历所有桶
for (var i = 0; i < n; i++) {
buckets[arr[i] - min]++
}
for (var i = 1; i < size; i++) {
//求前缀和
buckets[i] += buckets[i - 1];
}
var ret = [];//逆向遍历源数组(保证稳定性)
for (var i = n - 1; i >= 0; i--) {
buckets[arr[i] - min]--;
ret[buckets[arr[i] - min]] = arr[i];
}
return ret;
}
console.log(countSort([1, 0, 3, 1, 0, 1, 1]))
console.log(countSort([0, 5, 3, 2, 2]))
console.log(countSort([-2, -5, -45])) |
快排 function swap(array, a, b) {
var temp = array[a];
array[a] = array[b];
array[b] = temp;
}
function quickSort(array) {
function QuickSort(array, left, right) {
if (left < right) {
var index = partition3(array, left, right);
QuickSort(array, left, index - 1);
QuickSort(array, index + 1, right);
}
}
QuickSort(array, 0, array.length - 1);
return array
}
function partition(array, left, right) {//分治函数
var pivot = array[right];
var pivotIndex = right;
while (left < right) {
while (left < right && array[left] <= pivot) {
// 1. 防止越界需要left < right
// 2. array[left] <= pivot 因为可能存在相同元素,
left++; //找到比pivot大
}
while (left < right && array[right] >= pivot) {
right--; //找到比pivot小
}
swap(array, left, right);
}
//最后一个比pivot大的left元素要与pivot相交换
swap(array, left, pivotIndex);
return left; //返回的是中间的位置
}
function partition2(array, left, right) {//分治函数
var pivot = array[right];
var pivotIndex = right;
while (left < right) {
while (left < right && array[left] <= pivot) {
// 1. 防止越界需要left < right
// 2. array[left] <= pivot 因为可能存在相同元素,
left++; //找到比pivot大
}
array[right] = array[left]
while (left < right && array[right] >= pivot) {
right--; //找到比pivot小
}
array[left] = array[right]
}
//最后一个比pivot大的left元素要与pivot相交换
array[right] = pivot
return right; //返回的是中间的位置
}
function partition3(arr, left, right) {
var cur = left; //找大数
var prev = cur - 1; //找小数
var key = arr[right];
while (cur <= right) {
if (arr[cur] <= key && ++prev != cur)
swap(arr, prev, cur);
cur++;
}
return prev;
}
console.log(quickSort([4, 1, 7, 6, 9, 2, 8, 0, 3, 5]))
console.log(quickSort([1, 0, 3, 1, 0, 1, 1]))
console.log(quickSort([0, 5, 3, 2, 2]))
console.log(quickSort([-2, -5, -45])) |
冒泡排序
The text was updated successfully, but these errors were encountered: