十大内部排序,整个排序过程不需要借助于外部存储器(如磁盘等),所有排序操作都在内存中完成。
选择排序:堆排序、直接选择排序 ;交换排序:冒泡排序、快速排序 ; 插入排序:直接插入排序、折半插入排序、Shell排序(希尔排序); 归并排序;桶式排序;基数排序;
交换排序
冒泡排序
思路:将相邻的两个值进行比较,若发现逆序则交换,每次最外层循环找出未排序的一个最大值。
图解:
例:
public static void BubbleSort(int[] tage){
for (int i = 1; i < tage.length; i++) {
int swap = 0; //定义:当swap=0时,表示上次循环没有任何元素发生交换,即数组以排好序,提前退出循环
for (int j = 1; j <= tage.length-i; j++) {
if (tage[j]<tage[j-1]){
int temp = tage[j-1];
tage[j-1] = tage[j];
tage[j] = temp;
swap = 1;
}
}
if (swap==0){
break;
}
}
}
空间复杂度:O(1)
时间复杂度:O(n^2)
是否稳定:稳定
快速排序
快速排序(Quick Sorting)是迄今为止所有内排序算法中速度最快的一种它的基本思想是:任取待排序序列中的某个元素作为标准(也称为支点、界点,一般取第一个元素),通过一次划分,将待排元素分为左右两个子序列,左子序列元素的排序码均小于基准元素的排序码,右子序列的排序码则大于或等于基准元素的排序码,然后分别对两个子序列继续进行划分,直至每一个序列只有一个元素为止。最后得到的序列便是有序序列。
图解:
例:
/*快排*/
public static void QuickSort(int[] tage) {
int left = 0, right = tage.length-1;
QuickStart(tage,left,right);
}
private static void QuickStart(int[] tage, int L, int R) {
if (L > R){
return;
}
int left = L, right = R;
int point = tage[left];
while (left<right){
while (left<right && tage[right] >= point){ //在右边找到小于point的值
right--;
}
if (left < right){ //如果找到的值位置在point后,将小于point的值赋值于point左边
tage[left] = tage[right];
}
while (left<right && tage[left] <= point){ //在左边找到大于point的值
left++;
}
if (left < right){ //如果找到的值位置在point前,将大于point的值赋值于point右边
tage[right] = tage[left];
}
if (left>=right){
tage[left] = point;
}
}
QuickStart(tage,L,right-1); //递归左半,即小于point的部分
QuickStart(tage,right+1,R); //递归右半,即大于point的部分
}
空间复杂度:O(1)
时间复杂度:O(n^2)
是否稳定:不稳定
插入排序
直接插入排序
直接插入排序的基本思想是:把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将它插入到有序表中的适当位置,使之成为新的有序表。
图解:
例:
public static void InsertSortDirectly(int[] tage) {
int n = tage.length;
int i = 0, j = 0;
int temp;
for (i = 1; i < n; i++) { /*i控制第i-1 次插入,最多进行n-1次插入*/
if (tage[i] < tage[i - 1]) //件小于时, 需将tage[i]插入有序表
{
temp = tage[i];/* 为统一算法设置监视哨 */
for (j = i - 1;j>=0 && temp < tage[j]; j--){
tage[j + 1] = tage[j];/*元素后移*/
}
tage[j + 1] = temp; /*将放在temp中的第i个元素插入到有序表中*/
}
}
}
空间复杂度:O(1)
时间复杂度:O(n^2)
是否稳定:稳定
Shell排序(希尔排序)
希尔排序的基本思想:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率_上有较大提高。
图解:
例:
public static void ShellSort(int[] tage){
int group = tage.length;
int i=0,j=0;
while (group!=1){
group /= 2; //进行分组
for (i = 0; i < tage.length-group; i++) { //对每组进行直接插入排序,所以每组最大的排序次数为(组数-1),即有n组,所以数组长度-组数为当前需要遍历的最大次数
int end = i;
int temp = tage[end+group];
while (end>=0){
if (temp<tage[end]){ //符合条件进行交换
tage[end+group] = tage[end];
end -= group;
}else {
break;
}
}
tage[end+group] = temp;
}
}
}
空间复杂度:O(1)
时间复杂度:O(nlog2^n)~O(n^2)
是否稳定:不稳定