常见的排序算法

本文详细介绍了如何通过递归判断一个对象是否存在循环引用的问题,提供了一个名为`hasLoop`的函数实现。此外,还探讨了四种常见的排序算法——选择排序、插入排序、希尔排序和归并排序的实现细节,包括它们的时间复杂度和稳定性特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

判断一个对象是否是循环引用

判断对象与源是否相等即可

但是对象中会嵌套对象,源的数量不只一个,即不只外层对象,还有可能是外层对象的外层对象等,因此需要递归判断每个对象中的属性,并传递一个源的数组。

function hasLoop(obj){
	// 判断对象内部是否有和源相同的属性
	function findLoop(target, src){
		// 源数组,并将自身传入
		const source = src.slice().concat([target])
		
		for(const key in target){
			// 如果是对象才需要判断
			if(typeof target[key] === 'object'){
				// 如果在源数组中找到 || 递归查找内部属性找到相同
				if(source.indexOf(target[key]) > -1 || findLoop(target[key], source)){
					return true
				}
			}
		}
		return false
	}
	// 如果传入值是对象,则执行判断,否则返回false
	return typeof obj === 'object' ? findLoop(obj, []) : false;

排序算法

稳定:冒泡、插入、归并

不稳定:选择、快速、堆排序、希尔排序

  • 选择排序
// 选择排序
function selectSort(arr) {
    var len = arr.length;
    //先把第一个选中
    for(let i = 0 ;i < len - 1; i++) {
        // 让他和其他的依次比较,小就直接换位
        for(let j = i ; j<len; j++) {
            if(arr[j] < arr[i]) {
                [arr[i],arr[j]] = [arr[j],arr[i]];
            }
        }
    }
    return arr
}
  • 插入排序
// 插入排序
function insertSort(arr) {
    //外循环从1开始,默认arr[0]是有序段
    for(let i = 1; i < arr.length; i++) {  
        //j = i,将arr[j]依次插入有序段中
        for(let j = i; j > 0; j--) {  
            if(arr[j] < arr[j-1]) {
                [arr[j],arr[j-1]] = [arr[j-1],arr[j]];
            }
        }
    }
    return arr;
}
  • 希尔排序
// 希尔排序
function shellSort(arr,gap) {
    console.log(arr)//为了方便观察过程,使用时去除
    for(let i = 0; i<gap.length; i++) {  //最外层循环,一次取不同的步长,步长需要预先给出
        let n = gap[i]; //步长为n
        for(let j = i + n; j < arr.length; j++) { //接下类和插入排序一样,j循环依次取后面的数
            for(let k = j; k > 0; k-=n) { //k循环进行比较,和直接插入的唯一区别是1变为了n
                if(arr[k] < arr[k-n]) {
                    [arr[k],arr[k-n]] = [arr[k-n],arr[k]];
                    console.log(`当前序列为[${arr}] \n 交换了${arr[k]}和${arr[k-n]}`)//为了观察过程
                } else {
                    continue;
                }
            }
        }
    }
    return arr;
}
  • 归并排序
// 归并排序
function merge(leftArr, rightArr){  
    var result = [];  
    while (leftArr.length > 0 && rightArr.length > 0){  
      if (leftArr[0] < rightArr[0])  
        result.push(leftArr.shift()); //把最小的最先取出,放到结果集中   
      else   
        result.push(rightArr.shift());  
    }   
    return result.concat(leftArr).concat(rightArr);  //剩下的就是合并,这样就排好序了  
}  

function mergeSort(array){  
    if (array.length == 1) return array;  
    var middle = Math.floor(array.length / 2);       //求出中点  
    var left = array.slice(0, middle);               //分割数组  
    var right = array.slice(middle);  
    return merge(mergeSort(left), mergeSort(right)); //递归合并与排序  
}  

var arr = mergeSort([32,12,56,78,76,45,36]);
console.log(arr);   // [12, 32, 36, 45, 56, 76, 78]
  • 快速排序
// 快速排序
function quickSort(arr) {
    if(arr.length <= 1) {
        return arr;  //递归出口
    }
    var left = [],
        right = [],
        current = arr.splice(0,1); //注意splice后,数组长度少了一个
    for(let i = 0; i < arr.length; i++) {
        if(arr[i] < current) {
            left.push(arr[i])  //放在左边
        } else {
            right.push(arr[i]) //放在右边
        }
    }
    return quickSort(left).concat(current,quickSort(right)); //递归
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值