Java八大排序

1.冒泡排序

两层循环,外层循环控制轮数,内层循环做比较。
两两比较,大者交换位置,则每一轮循环结束后最大的数就会移动到最后。
时间复杂度为O(n^2);空间复杂度为O(1);

int[] nums = new int[] {4,5,1,6,8,2,3,9};
int temp = 0;
for(int i=0;i<nums.length-1;i++){
	//外层循环length-1次
	for (int j = 0; j < nums.length-i-1; j++) {
		//外层每循环一次最后内层都会排好一个数
		//所以内层循环length-1-i次
	    if(nums[j] > nums[j+1]){
        	temp = nums[j+1];
            nums[j+1] = nums[j];
            nums[j] = temp;
        }
	}
}

2.快速排序

快速排序是对冒泡排序的一种改进,借用了分治的思想:通过一轮排序将要排序的数据分成独立的两部分,其中一部分的数据比另一部分的所有数据都小,然后再对这两个小部分数据分别进行快速排序,整个排序过程可以递归进行,以此达打到所有数据都变成有序序列。
时间复杂度为O(n*logn);空间复杂度O(1)
基本步骤

  1. 从数列中挑出一个元素,称为“基准”(pivot)
  2. 重新排列数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以任意到一边)。分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
  3. 递归的把小于基准值元素的子数列和大于基准值元素的子数列排序。
  4. 递归到最底部时,数列的大小是0或者1,也就是已经排序好了。这个算法一定会结束,因为再每次的迭代中,它至少会把一个元素摆到它最后的位置去。
public static void quickSort(int[] array,int start, int end){
	if(start<end){
		int baseNum = array[start];//基准值
		int left = start;//左指针
		int right = end;//右指针
		int midNum;
		while(left<=right){
			while(array[left]<baseNum && left<end){
				left++;
			}
			while(array[right]<baseNum && right>start){
				right--;
			}
			if(left<right){
				middNum = array[left];
				array[left] = array[right];
				array[right] = midNum;
			}
			if(start<left){
				quickSort(array, start, left);
			}
			if(end>right){
				quickSort(array, right, end);
			}
		}
	}
}

3.插入排序

直接插入排序(Straight Insertion Sorting) 的基本思想: 将数组中的所有元素依次跟前面已经排好的元素比较,如果选择的元素比已排序的元素值小,则交换,直到全部元素都比较过为止。

  • 外层循环确定比较轮数。第一个数不用
  • 确定插入数和得到已经排好序列的最后一个数的位数,内层循环每轮的循环次数,insertNum和j=i-1
public static void insertSort(int[] array){
	int current;//插入数
	for(int i=1;i<array.length;i++){
		int j = i-1;//已排序序列的末位索引
		current = array[i]
		while(j>=0 && array[j]>current){//从后往前,将大于当前插入数的值往后移
			array[j+1] = array[j];
			j--;
		}
		array[j] = current;//找到位置,插入当前插入数
	}
}

4.选择排序

  • 遍历整个序列,将最小的数放在最前面
  • 遍历剩下的序列,将最小的数放在最前面。
  • 重复第二步,直到只剩下一个数。
public static void chooseSort(int[] array){
	for(int i=0;i<array.length;i++){
		int minNum = array[i];//最小值
		int index = i;//最小值索引
		for(int j=i+1;j<array.length;j++){//找到最小值
			if(minNum>array[j]){
				minNum = array[j];
				index = j;
			}
		}
		array[index] = array[i];//交换当前值和最小值的位置
		array[i] = minNum;
		
	}
}

5.基数排序

用于大量数,很长的数进行排序。

  • 将所有的数的个位数取出,按照个位数进行排序,构成一个序列。
  • 将新构成的所有的数的十位数取出,按照十位数进行排序,构成一个序列。
  • 以此类推,百位数···
还不会链表

6.希尔排序

插入排序的一种高速而稳定的改进版本。

  • 希尔排序时先将整个待排序的序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录依次直接插入排序。
  • 简单来讲,就是将整个序列分成若干个子序列,而每个子序列就相当于数学里面周期函数的一周期,然后将第一个周期里的数据不断地跟后面每个周期相同位置的值比较,小的数据换到前面,大的数据换到后面,通过不断压缩一个周期的长度来精确。
public static void shellSort(int[] array){
	int gap = array.length / 2;//进行分组(分成两周期)
	for( ; gap < array.length; gap = gap /2){//缩小子序列周期
		for(int j = 0; (j + gap) < array.length; j++){//重复进行
			for(int k = 0; (k+gap)<array.length; k += gap){
				if(array[k] > array[k+gap]){
					int temp = array[k];
					array[k] = array[k + gap];
					array[k + gap} = temp;
				}
			}
		}
	}
}

7.归并排序

速度仅次于快速排序,内存少的时候使用,可以进行并行计算的时候使用。

  • 选择相邻两个数组成一个有序序列。
  • 选择相邻的两个有序序列组成一个有序序列。
  • 重复第二步,直到全部组成一个有序序列。
public static void mergeSort(int[] array){
        int sum = array.length;//初始序列组数
        int element = 1;//初始序列元素
        boolean boo = false;//为true时最后一次为不规则序列排序
        while(sum > 1){//当sum等于1时完成排序
            int remainder = sum % 2;//是否有落单的序列
            if(remainder == 1){
                boo = true;
            }
            int sepuence = sum / 2;
            sum = remainder + sepuence;//剩余序列数
            int n = 0;//排序次数
            int s = element * 2;//当前两序列元素和
            int[] data = new int[array.length];
            int r = 0;//data指针
            while(n<sum){
                int left = n * s;//左指针
                int right = n * s + element;//右指针
                if(boo && remainder == 1 && n == sum - 1){
                    for(; r < array.length; r++){
                        data[r] = array[r];
                    }
                }
                else{
                    while(r < (n + 1) * s){
                        if((array[left] <= array[right] && left <n * s + element)|| right==(n+1)*s){
                            data[r] = array[left];
                            left++;
                        }
                        else{
                            data[r] = array[right];
                            right++;
                        }
                        r++;
                    }//排序
                }
                n++;
            }
            for(int i=0; i<array.length; i++){
                array[i] = data[i];
            }
            element = s;//下一次排序时的序列元素数
        }
    }

8.堆排序

堆(二叉堆): 可以视为一颗完全的二叉树,完全二叉树的一个"优秀"的性质就是:除了最底层之外,每一层都是满的,这使得堆可以利用数组来表示(一般的二叉树通常用链表作为基本容器表示),每一个节点对应数组中的一个元素。
在这里插入图片描述
对于给定的某个节点的下标i(0开始),可以很容的计算出该节点的父节点,子节点的下标:

parent 	= (i+1)/2 - 1;		//i的父节点下标
left 	= 2*(i+1) - 1;		//i的左子节点下标
right	= 2*(i+1);			//i的右子节点下标

二叉堆一般分为两种:最大堆和最小堆。

  • 分别找到i元素的左孩子和右孩子,若左孩子与右孩子中右比i元素大的,找到最大的那个元素,并且与i元素交换位子,对交换位子的那个最大元素再次重复上诉步骤。注意:此方法成立的条件是i元素的左子树与右子树都是最大堆!!!
public static void heapSort(int[] array){
	int len = array.length; //剩余未排序序列的长度
	int temp = 0;
	while(len > 1){
		for(int i = len / 2; i > 0; i--){
			if((2 * i - 1) < len && array[2 * i - 1] > array[i - 1]){
				//若左子节点值大于该节点,则交换位置
				temp = array[2 * i - 1];
				array[2 * i - 1] = array[i - 1];
				array[i - 1] = temp;
			}
			if(2 * i < len && array[2 * i] > array[i - 1]){
				//若右子节点值大于该节点,则交换位置
				temp = array[2 * i];
				array[2 * i] = array[i - 1];
				array[i - 1] = temp;
			}
		}
		//此时array为最大值,交换位置到最后去
		temp = array[0];
		array[0] = array[len - 1];
		array[len - 1] = temp;
		len--;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
选择排序算法准则: 每种排序算法都各有优缺点。因此,在实用时需根据不同情况适当选用,甚至可以将多种方法结合起来使用。 选择排序算法的依据 影响排序的因素有很多,平均时间复杂度低的算法并不一定就是最优的。相反,有时平均时间复杂度高的算法可能更适合某些特殊情况。同时,选择算法时还得考虑它的可读性,以利于软件的维护。一般而言,需要考虑的因素有以下四点: 1.待排序的记录数目n的大小; 2.记录本身数据量的大小,也就是记录中除关键字外的其他信息量的大小; 3.关键字的结构及其分布情况; 4.对排序稳定性的要求。 设待排序元素的个数为n. 1)当n较大,则应采用时间复杂度为O(nlog2n)的排序方法:快速排序、堆排序或归并排序序。 快速排序:是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短; 堆排序 : 如果内存空间允许且要求稳定性的, 归并排序:它有一定数量的数据移动,所以我们可能过与插入排序组合,先获得一定长度的序列,然后再合并,在效率上将有所提高。 2) 当n较大,内存空间允许,且要求稳定性 =》归并排序 3)当n较小,可采用直接插入或直接选择排序。 直接插入排序:当元素分布有序,直接插入排序将大大减少比较次数和移动记录的次数。 直接选择排序 :元素分布有序,如果不要求稳定性,选择直接选择排序 5)一般不使用或不直接使用传统的冒泡排序。 6)基数排序 它是一种稳定的排序算法,但有一定的局限性:   1、关键字可分解。   2、记录的关键字位数较少,如果密集更好   3、如果是数字时,最好是无符号的,否则将增加相应的映射复杂度,可先将其正负分开排序

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值