选择排序:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。
for( int i = 0;i< data.length;i++){
int minIndex = i;
for( int j = i+1;j<data.length;j++){
if( data[j] < data[i]){
minIndex = j;
}
}
swap(data,i, minIndex);
}
private void swap(int arr,int i ,int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j]= temp;
}
选择排序的循环不变量
从[0,i)中的元素一直是经过了排序的,[i,n)是要排序的元素,在arr[i,n)中选择最小值。
选择排序的时间复杂度
外层的循环n次,内循环1+2+3.。。。+n次.等差数列求和。低阶和常数忽略,所以是O(n²)
插入排序:将一个新的记录插入到已经排好序的有序表中,直到插完为止。
//外循环相当于一个新的记录
for(int i = 0; i< arr.length; i++){
//内循环相当于将新的记录插入到排好序的记录中
for( int j = i; j-1>=0; j--){
//如果后一个比前面的小
if( arr[j] < arr[j-1]){
//不断前移
swap(arr,i,j-1);
}else{
break;
}
}
}
private void swap(int arr[],i,j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
//一个小优化
for (int i = arr.length-1; i >= 0; i--) {
//来一个中间变量记录这个 i
//将arr[i]插入到合适的位置
int temp = arr[i];
int j;
//我的错误写法,j=1;arr[j]>arr[j+1];j++
for (j = i; j-1>=0 && arr[j]<arr[j-1]; j--) {
arr[j] = arr[j-1];
}
arr[j] = temp;
}
插入排序的循环不变量
在[0,i)中是已经排好序的,将[i,n)中未排序的元素持续插入到已经排序的顺序中。
插入排序的特性
如果数据本身是有序的,内循环相当于进行了常数级别的操作。插入排序也就变成了O(n)级别。这也是和选择排序的区别。算法复杂度通常指的是最差的情况下。