- 冒泡排序
- 选择排序
- 插入排序
- 归并排序
- 计数排序(counting sort)
- 基数排序(radix sort)
- 希尔排序
- 堆排序
- 桶排序
先行条件
构造一个数组列表函数
function ArrayList(){this.array=[];//插入元素ArrayList.prototype.insert=function(item){this.array.push(item);}//以字符串输出数组列表元素ArrayList.prototype.toString=function(){return this.array.join("-");}}var list = new ArrayList(); //实例化list.insert(3);list.insert(6);list.insert(4);list.insert(2);list.insert(84);list.insert(966);list.insert(487);//交换两个位置的数据ArrayList.prototype.swap = function (pos1, pos2) {let temp = this.array[pos1];this.array[pos1] = this.array[pos2];this.array[pos2] = temp;}
冒泡排序 Bubble sort
对未排序的元素从头到尾依次比较相邻两个元素的关系
ArrayList.prototype.buubleSort = function () {//获取数组长度let length = this.array.length;for (let j = length - 1; j >= 0; j--) {for (let i = 0; i < j; i++) {if (this.array[i] > this.array[i + 1]) {this.swap(i, i + 1);}}}}console.log(list.toString())list.buubleSort();console.log(list.toString())
排序前:3-6-4-2-84-966-487
排序后:2-3-4-6-84-487-966
比较次数
大O表示法
公式:N*(N-1)/2
交换次数
大O表示法
公式:N*(N-1)/4
选择排序Select sort
选定第一个索引位置,依次跟后面的元素依次比较
如果后面的元素小于第一个索引的元素,则交换位置
经过一轮比较后就可以确认第一个位置是最小的
然后再使用同样的方法把剩下的元素比较
ArrayList.prototype.selectSort=function(){let length=this.array.length //获取数组列表长度//遍历数组的每一项元素//length-1 就是数组的最后一项,而最后一项不用比较的,因为已经排序过了for(let j=0;j<length-1;j++){let min=j; //定义变量min存储里层循环获取到的最小元素索引/*再次遍历数组元素 初始值等于min+1 因为外层循环的时候会把min等于外层循环索引而外层循环当前索引是不用在里层循环遍历的 之前的元素已经正确的排号位置了 所以直接跳过j4 9 5 6 81 2mi*/for(let i=min+1;i<length;i++){if(this.array[min]>this.array[i]){ //比较min索引的元素和遍历的每一个元素 哪个大min=i; //如果Min>里层遍历的元素 就把里层当前循环的索引赋值给min}}this.swap(min,j); //交换元素}}list.selectSort();console.log(list.toString());
结果输出:2-3-4-6-84-487-966
比较字数
大O表示法
公式:N*(N-1)/2
交换次数
大O表示法
公式:N-1
插入排序 Insert sort
插入排序的核心是局部有序
在一个数组中 选择其中一个作为标记元素
被标记元素左边所有元素已经排好顺序
意味着有一部分已经排好序,还有一部分是没有排序的
ArrayList.prototype.insertSort=function(){let length=this.array.length; //获取数组长度/*遍历数组里的每一个元素 从1开始,因为要示左边为以排序好,选择元素插入到左边排序好的位置*/for(let i=1;i<length;i++){let j=i; //j 算是一个指针 指遍历左边排序好的元素let temp=this.array[i] //temp 存储当前循环索引位置的元素数据//用while循环 因为不知道插到哪个位置//循环的条件是 如果数组j-1就是上一个元素大于temp(是当前循环索引位置的元素数据) 就执行循环体的指令while(this.array[j-1]>temp&&j>0){//把当前循环索引位置的元素数据换成上一个元素数据//例如:6 3 9 2 i=3 temp=3 j=3 j-1=6 j=j-1 就是j=6this.array[j]=this.array[j-1];//指针指向上一个元素j--}//插入temp的数据到j的位置this.array[j]=temp;}}
比较次数
公式:N*(N-1)/4
大O表示法:
复制次数
公式:N*(N-1)/2
希尔排序 Shell’s Sort
是插入排序的一种高效的进化版,并且效率比插入排序更快
通过指定的间隔来交换数组元素,尽量让最小的排到最前面,最后的尽量排到后面
间隔选择 Shell原稿
N / 2 N=数组长度
如果N=100 向下取整
100/2=50 50/2=25 25/2=12 12/2=6 6/2=3 3/2=1
ArrayList.prototype.ShellSort = function () {let length=this.array.length; //获取数组长度let gap=Math.floor(length/2); //间隔增量 为数组的长度除以2//循环,只要gap大于或者等于1 就执行循环体内的指令while(gap>=1){//遍历数组的每一个元素for(let i=gap;i<length;i++){let j=i; //把i复制给j j相当于指针let temp=this.array[i]; //把i的元素复制给temp 因为等一下i的元素会变/*循环,当j-gap大于temp的时候 j一开始是和gap相等,j-gap=0 如果索引为0的元素大于temp以及j>gap-1 这是为了防止越界*/while(this.array[j-gap]>temp&&j>gap-1){//就把j-gap的元素给j 执行到这里说明j-gap索引的元素大于j的元素 所以要调换位置 把大放到右边this.array[j]=this.array[j-gap];//j重新赋值 向左退gap步j-=gap;}this.array[j]=temp;}//每次gap都除以2 向下取整gap=Math.floor(gap/2);}}
例子:数组元素 [2 6 4 3 84 966 487]
0 1 2 3 4 5 6
2 6 4 3 84 966 487
let gap=Math.floor(length/2);
gap=7/2 3.5向下取整3
while(gap>=1)
while循环当gap<1的时候停止
for(let i=gap;i
let j=i;
每次循环都生命一个 j 指针变量 初始化为i j是用来向gap的左边递减寻找上一个gap的
let temp=this.array[i];
以及temp变量,存储 i 的元素值 因为等一下交换了元素后 i的值可能会变
while(this.array[j-gap]>temp){
this.array[j]=this.array[j-gap];
}
循环当数组的j-gap索引位置的元素 大于 temp 的时候就把j-gap的元素赋值给j
j-=gap;
每次j-=gap 相当于往左边进gap步 以到达下一个gap
this.array[j]=temp
最内层循环结束后就就把temp赋值给j
再次执行遍历循环
gap=Math.floor(gap/2);
遍历循环结束后 每次gap/2 向下取整 直到gap<=1就跳出循环
然后再次执行最外层while循环
快速排序Quick sort
重要的思想:分而治之
ArrayList.prototype.quickSort = function (arr) {let length = arr.length; //获取数组的长度//如果数组的长度小于1 就不用排序,直接返回数组if (length <= 1) {return arr;}let left = []; //存放小于基准的元素let right = []; //存放大于基准的元素let povit = arr[0]; //基准选取数组的一个元素//遍历数组的每一个元素for (let i = 1; i < length; i++) {//小于基准的就放到left数组if (arr[i] < povit) {left.push(arr[i]);} else {//大于基准的就放到right数组right.push(arr[i]);}}//递归调用方法//因为方法返回的是排序后数组 所以用排序后 小于基准的数组 合并 基准元素 以及排序后 大于基准的元素数组return this.quickSort(left).concat(povit, this.quickSort(right));}
平均效率
大O表示法:O(N*logN)
