1.排序算法都有哪些?
排序算法包括:
- 冒泡排序 选择排序 插入排序 归并排序 计数排序 基数排序 希尔排序 堆排序 桶排序 快速排序
2.冒泡排序
- 思路:假设有n个数据要进行比较,采用冒泡排序,每一个大循环比较交换得到最大的一个数(位于倒数,可以说这个最大的数不用在下一个大循环中再参与比较了),要进行大循环的次数是n次,而一个大循环中,需要比较交换的次数是n-进行大循环的次数,但是考虑到数组中是从下标0开始存数的,可以将内循环的次数改成从0到n-进行大循环的次数-1。
- 冒泡排序时间复杂度O(N^2)。
- 代码:
//交换两数
ArrayList.prototype.swap=function(m,n){
var temp=this.array[m];
this.array[m]=this.array[n];
this.array[n]=temp;
}
//冒泡排序,外层循环是大交换的轮次(有几个数据,就做几轮大循环),内循环是在一个大循环中交换的次数
ArrayList.prototype.bubble=function(){
var length=this.array.length;
for(var i=1;i<=length;i++){
for(var j=0;j<=length-1-i;j++){
if(this.array[j]>this.array[j+1]){
this.swap(j,j+1);
}
}
}
}
3.选择排序
- 思路:选定第一个索引位置,然后和后面的元素依次作比较,如果后面的更小,则交换,经过一轮之后,第一个位置的元素就是最小的,然后选择第二个索引位置,和后面的元素作比较,一轮之后,就确定第二小了…经过n轮后,排序完成。外层循环做的事是确定索引位置,索引的位置可以取[0,n-,2],内层循环做的事是取索引之后的元素与索引位置的元素作比较,所以可以取得范围是[索引值+1,n-1],因为是存于数组当中的,所以第一个元素的索引值为0,最后一个元素的索引值为n-1,倒数第二的元素的索引值为n-2.
- 选择排序时间复杂度O(N^2)。 通常情况下,选择排序在执行效率上比冒泡高,因为两者的比较次数差不多,但是交换次数,选择排序更少(n-1次)。
- 代码:
//选择排序
ArrayList.prototype.select=function(){
var length=this.array.length;
for(var i=0;i<=length-2;i++){
for(var j=i+1;j<=length-1;j++){
if(this.array[i]>this.array[j]){
this.swap(i,j);
}
}
}
}
4.插入排序
- 思路:插入排序的核心是局部有序。它的基本思想是将一个记录插入到已经排好序的有序表中,从而形成一个新的记录数增 1 的有序表。在其实现过程使用双层循环,外层循环是除了第一个元素之外的所有元素(我们把外层循环叫做记号表,范围是[1,n-1]),内层循环(是一个有序表,范围是[0,当前记号的索引-1]),我们从记号表中取一个记号和有序表中的元素比较,如果当前记号更小,则把记号插入到有序表中比记号稍微大的元素的位置上,然后删除记号表中的这个记号;如果记号比有序表中任意元素都大,则不插入。
- 插入排序的平均时间复杂度也是 O(n^2), 空间复杂度为常数阶O(1),插入排序中,当待排序数组是有序时,是最优的情况,只需当前数跟前一个数比较一下就可以了,这时一共需要比较 N-1 次,时间复杂度为O(N)。最坏的情况是待排序数组是逆序的,此时需要比较次数最多,最坏的情况是 O(n^2)。
- 代码:
//插入排序
ArrayList.prototype.insertSort=function(){
var length=this.array.length;
for(var i=1;i<=length-1;i++){
for(var j=0;j<=i-1;j++){
if(this.array[i]<this.array[j]){`在这里插入代码片`
this.array.splice(j,0,this.array[i]);
this.array.splice(i+1,1);
break;
}
else{
continue;
}
}
}
}
5.希尔排序
- 思路:它通过比较相距一定间隔的元素来进行,各趟比较所用的距离随着算法的进行而减小,直到只比较相邻元素的最后一趟排序为止。
- 希尔排序时间复杂度是 O(n^(1.3-2)),空间复杂度为常数阶 O(1)。 希尔排序没有时间复杂度为 O(n(logn))的快速排序算法快 ,因此对中等大小规模表现良好,但对规模非常大的数据排序不是最优选择,总之比一般 O(n^2 ) 复杂度的算法快得多。
- 代码:
//希尔排序
ArrayList.prototype.shell=function(){
var length=this.array.length;
var gap=Math.floor(length/2);
while(gap>=1){
for(var i=gap;i<=length-1;i++){
var temp=this.array[i];
var j=i;
while(this.array[j-gap]>temp&&j>gap-1){
this.array[j]=this.array[j-gap];
j-=gap;
}
this.array[j]=temp;
}
gap=Math.floor(gap/2);
}
}
6.双路快速排序
- 思路:快速排序就是给基准数据找到正确位置。首先,我们把数组第一个数当做基准数据用temp存起来,让left在索引为0的地方,让right在索引为n-1的地方,从后面开始,如果array[right]>temp,right就减减,否则就让array[left]=array[right],接着轮到前面了,如果array[left]<temp,left++,否则,array[right]=array[left],这里一直做循环(循环条件是left<right),之后等到循环结束left=right时,让array[left]=temp,说明找到了放基准数据的正确位置,然后返回这个位置,让[left,返回位置-1]再找基准数据,放基准数据;让[返回位置+1,right]再找基准数据,放基准数据.
- 快速排序是一种比较快速的排序算法,它的平均运行时间是 O(nlogn),之所以特别快是由于非常精练和高度优化的内部循环,最坏的情形性能为O(n^2)。像归并一样,快速排序也是一种分治的递归算法。从空间性能上看,快速排序只需要一个元素的辅助空间,但快速排序需要一个栈空间来实现递归,空间复杂度也为O(logn)。
- 代码:
//双路快速排序
ArrayList.prototype.quick=function(left,right){
if(left<right){
var p=this.position(left,right);
this.quick(left,p-1);
this.quick(p+1,right);
}
}
ArrayList.prototype.position=function(left,right){
var temp=this.array[left];
while(left<right){
while(this.array[right]>temp&&left<right){
right--;
}
this.array[left]=this.array[right];
while(this.array[left]<=temp&&left<right){
left++;
}
this.array[right]=this.array[left];
}
this.array[left]=temp;
return left;
}
7.归并排序
- 思路:该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。
- 归并排序的时间复杂度为 O(nlogn)。归并排序时需要和待排序记录个数相等的存储空间,所以空间复杂度为 O(n)。
- 代码:
function merge(left, right) {
let result = new Array();
let i = 0, j = 0
while(i < left.length && j < right.length) {
if (left[i] <= right[j]) {
result.push(left[i++])
} else {
result.push(right[j++])
}
}
if (i < left.length) {
result.push(...left.slice(i))
} else {
result.push(...right.slice(j))
}
return result
}
function mergeSort(array) {
if (array.length < 2) {
return array
}
let m = Math.floor(array.length / 2)
var left = mergeSort(array.slice(0, m))
var right = mergeSort(array.slice(m))
return merge(left, right)
}
var array=[66,68,12,87,100,5,566,23];
console.log(mergeSort(array))
最后,附上这些排序的完整代码
//创建封装类
function ArrayList(){
//属性
this.array=[];
//方法
//将数据插入到数组中
ArrayList.prototype.insert=function(data){
this.array.push(data);
}
//toString方法
ArrayList.prototype.toString=function(){
return this.array.join(' ');
}
//交换两数
ArrayList.prototype.swap=function(m,n){
var temp=this.array[m];
this.array[m]=this.array[n];
this.array[n]=temp;
}
//冒泡排序,外层循环是大交换的轮次(有几个数据,就做几轮大循环),内循环是在一个大循环中交换的次数
ArrayList.prototype.bubble=function(){
var length=this.array.length;
for(var i=1;i<=length;i++){
for(var j=0;j<=length-1-i;j++){
if(this.array[j]>this.array[j+1]){
this.swap(j,j+1);
}
}
}
}
//选择排序
ArrayList.prototype.select=function(){
var length=this.array.length;
for(var i=0;i<=length-2;i++){
for(var j=i+1;j<=length-1;j++){
if(this.array[i]>this.array[j]){
this.swap(i,j);
}
}
}
}
//插入排序
ArrayList.prototype.insertSort=function(){
var length=this.array.length;
for(var i=1;i<=length-1;i++){
for(var j=0;j<=i-1;j++){
if(this.array[i]<this.array[j]){
this.array.splice(j,0,this.array[i]);
this.array.splice(i+1,1);
break;
}
else{
continue;
}
}
}
}
//希尔排序
ArrayList.prototype.shell=function(){
var length=this.array.length;
var gap=Math.floor(length/2);
while(gap>=1){
for(var i=gap;i<=length-1;i++){
var temp=this.array[i];
var j=i;
while(this.array[j-gap]>temp&&j>gap-1){
this.array[j]=this.array[j-gap];
j-=gap;
}
this.array[j]=temp;
}
gap=Math.floor(gap/2);
}
}
//双路快速排序
ArrayList.prototype.quick=function(left,right){
if(left<right){
var p=this.position(left,right);
this.quick(left,p-1);
this.quick(p+1,right);
}
}
ArrayList.prototype.position=function(left,right){
var temp=this.array[left];
while(left<right){
while(this.array[right]>temp&&left<right){
right--;
}
this.array[left]=this.array[right];
while(this.array[left]<=temp&&left<right){
left++;
}
this.array[right]=this.array[left];
}
this.array[left]=temp;
return left;
}
}
//测试
var array=new ArrayList();
array.insert(66);
array.insert(88);
array.insert(12);
array.insert(87);
array.insert(100);
array.insert(5);
array.insert(566);
array.insert(23);
console.log(array.toString());//66 88 12 87 100 5 566 23
array.bubble();
console.log("冒泡排序后:"+array.toString());//冒泡排序后:5 12 23 66 87 88 100 566
array.select();
console.log("选择排序:"+array.toString());//选择排序:5 12 23 66 87 88 100 566
array.insertSort();
console.log('插入排序:'+array.toString());//插入排序:5 12 23 66 87 88 100 566
array.shell();
console.log('希尔排序'+array.toString());//希尔排序5 12 23 66 87 88 100 566
array.quick(0,7);
console.log("快速排序:"+array.toString());//快速排序:5 12 23 66 87 88 100 566