1、排序算法
(1)插入排序
① 直接插入排序
把n个待排序的元素看成为一个有序表和一个无序表。开始时有序表中只包含1个元素,无序表中包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,将它插入到有序表中的适当位置,使之成为新的有序表,重复n-1次可完成排序过程。
因此,从上面的描述中我们可以发现,直接插入排序可以用两个循环完成:
第一层循环:遍历待比较的所有数组元素
第二层循环:将本轮选择的元素(selected)与已经排好序的元素(ordered)相比较。
<script>
var arr=[54,6,2,8,13,3]
for(var i=0;i<arr.length;i++){
console.log("i的值"+i)
var temp=arr[i] //第i个的值拿出来
var j=i-1
while(j>=0 && arr[j]>temp){//判断循环的条件
arr[j+1]=arr[j]//如果大的话,后移动一位
j--; //j做减法然后继续和前一个判断
console.log("j的值"+j)
}
arr[j+1]=temp
}
document.writeln(arr)
//i=0时不符合 j=-1不执行内层循环
//i=1时j=0,arr[j]=0 54>6 执行内层循环 a1=a0 将54后移动 6 54 2 8 13 3 j减1后为0
//i=2时j=1,arr[j]=54 54>2 执行内层循环 a2=a1 将54后移动 6 2 54 8 13 3
</script>
var x=[23,5,2,6,7,57]
for(var i=0;i< x.length;i++){
var temp=x[i]
for(j=i-1;j>=0&&x[j]>temp;j--){
x[j+1]=x[j]
}
x[j+1]=temp
}
document.writeln(x)
② 希尔排序
选择一个增量序列 t1,t2,……,tk,其中 ti > tj, tk = 1;
按增量序列个数 k,对序列进行 k 趟排序;
每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
var arr = [49, 38, 65, 97, 76, 13, 27, 49, 55, 04];
var len = arr.length;
for (var fraction = Math.floor(len / 2); fraction > 0;
fraction = Math.floor(fraction / 2)) {
document.writeln("第一次分组"+fraction+"<br>")
for (var i = fraction; i < len; i++) {
document.writeln("第二次分组"+fraction+"<br>")
for (var j = i - fraction; j >= 0 && arr[j] > arr[fraction + j]; j -= fraction) {
document.writeln("第三次分组"+fraction+"<br>")
var temp = arr[j];
arr[j] = arr[fraction + j];
arr[fraction + j] = temp;
}
}
}
document.writeln(arr)
进行分组+直接插入排序
(2)选择排序
① 简单选择排序
L[1,2,3,4,5,6…n]
从i=0开始循环前边放有序的,找到后边L[i…n]中最小的数字与L[i]进行交换
例如 arr=[30,24,67,2,8,56]
第1趟2,24,67,30,8,56
第2趟2,8,67,30,24,56
第3趟2,8,24,30,67,56
第4趟2,8,24,30,56,67
第5趟2,8,24,30,56,67
2,8,24,30,56,67
var arr=[30,24,67,2,8,56]
for(i=0;i< arr.length;i++){
var min=i;//记录最小的位置即L[i],后续要将之后的数组中的最小的值与之进行交换
for(j=i+1;j<arr.length;j++){
if(arr[j]<arr[min]){
min=j
}
}
var temp=arr[min];
arr[min]=arr[i]
arr[i]=temp
}
document.writeln(arr+"<br>")
空间效率为O(1)
元素移动次数很少,当表有序时移动次数为0,但比较的次数与表的次序无关,所以时 间复杂度始终为O(n2)
不稳定的算法
② 堆排序
(3)交换排序
① 冒泡排序
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
var arr=[23,6,24,8,6,44,35]
for(i=0;i<arr.length;i++){
for(j=0;j<i;j++){
if(arr[j]>arr[j+1]){
var temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp
}
}
}
document.writeln(arr+"<br>")
② 快速排序
a.首先设定一个分界值,通过该分界值将数组分成左右两部分。
b.将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值。
c.然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
d.重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成
var arr=[30,67,2,8,56]
function sort(arr,from,to){
var i=from//左哨兵
var j=to;//右哨兵
var key=arr[from]//标准值
if(from>=to){//如果数组只有一个元素
return
}
while(i<j){
while(arr[j]>key&& i < j){
j--
}
while(arr[i]<=key&& i < j){
i++
}
if(i<j){
var temp=arr[i]
arr[i]=arr[j]
arr[j]=temp
}
}
arr[from] = arr[i]
arr[i] = key;
sort(arr,from,i-1);
sort(arr,i+1,to);
}
sort(arr,0,arr.length-1)
console.log(arr)
(4)归并排序
(5)基数排序