将一个记录插入到已经排序好的有序表中,从而得到一个新的表,记录数增1的有序表
public static void insertSort(int [] nums){
for(int i = 1; i < nums.length; i++){
int temp = nums[i];
int j = i - 1;
for(; j >= 0; j--){
if(nums[j] > temp){
nums[j+1] = nums[j];
}else{
break;
}
}
nums[j+1] = temp;
}
}
先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。
public static void shellSort(int [] nums){
int gap = nums.length;
while(gap > 1){
shell(nums,gap);
gap = (gap/3)+1;
}
shell(nums,1);
}
public static void shell(int [] nums, int gap){
for(int i = gap; i < nums.length; i++){
int temp = nums[i];
int j = i - gap;
for(;j >= 0; j = j - gap){
if(nums[j] > temp){
nums[j+gap] = nums[j];
}else{
break;
}
}
nums[j+gap] = temp;
}
}
每一次从无序区间选出最大(或最小)的一个元素,存放在无序区间的最后(或最前),直到全部待排序的数据元素排完 。
第一趟,从n 个记录中找出关键码最小的记录与第一个记录交换;
第二趟,从第二个记录开始的n-1 个记录中再选出关键码最小的记录与第二个记录交换;
以此类推…
第i 趟,则从第i 个记录开始的n-i+1 个记录中选出关键码最小的记录与第i 个记录交换,直到整个序列按关键码有序。
public static void selection(int [] nums){
for (int i = 0; i < nums.length - 1; i++) {
int j = i + 1;
int index = i;
for(; j < nums.length; j++){
if(nums[j] < nums[index]){
index = j;
}
}
if(index != i){
int temp = nums[index];
nums[index] = nums[i];
nums[i] = temp;
}
}
}
排升序要建大堆,排降序建小堆。
public static void heapSort(int[] arr){
for(int i = arr.length; i > 0; i--){
max_heapify(arr, i);
//堆顶元素(第一个元素)与Kn交换
int temp = arr[0];
arr[0] = arr[i-1];
arr[i-1] = temp;
}
}
private static void max_heapify(int[] arr, int limit){
if(arr.length <= 0 || arr.length < limit)
return;
int parentIdx = limit / 2 - 1;
for(; parentIdx >= 0; parentIdx--){
if(parentIdx * 2 >= limit){
continue;
}
//左子节点位置
int left = parentIdx * 2 + 1;
//右子节点位置,如果没有右节点,默认为左节点位置
int right = (left + 1) >= limit ? left : (left + 1);
int maxChildId = arr[left] >= arr[right] ? left : right;
//交换父节点与左右子节点中的最大值
if(arr[maxChildId] > arr[parentIdx]){
int temp = arr[parentIdx];
arr[parentIdx] = arr[maxChildId];
arr[maxChildId] = temp;
}
}
System.out.println("Max_Heapify: " + Arrays.toString(arr));
}
在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。
public static void bubbleSort(int [] nums){
for (int i = 0; i < nums.length - 1; i++) {
for (int j = i+1; j < nums.length; j++) {
if(nums[j] < nums[i]){
int temp = nums[j];
nums[j] = nums[i];
nums[i] = temp;
}
}
}
}
基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。
public static int pivot(int [] nums,int start, int end){
int temp = nums[start];
while(start < end){
while(start < end && nums[end] >= temp){
end--;
}
nums[start] = nums[end];
while(start < end && nums[start] <= temp){
start++;
}
nums[end] = nums[start];
}
nums[start] = temp;
return start;
}
public static void quick(int [] nums, int low, int high){
if(low < high){
int piv = pivot(nums,low,high);
quick(nums,low,piv - 1);
quick(nums,piv + 1,high);
}
}
归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
public static void mergeSort(int [] array){
mergeSortInternal(array,0,array.length - 1);
}
public static void mergeSortInternal(int [] array,int low, int high){
if(low >= high){
return;
}
int mid = (low+high)/2;
mergeSortInternal(array,low,mid);
mergeSortInternal(array,mid+1,high);
merge(array,low,mid,high);
}
public static void merge(int [] array, int start,int mid,int end){
int s1 = start;
int e1 = mid;
int s2 = mid + 1;
int e2 = end;
int [] temp = new int [end-start+1];
int k = 0;
while(s1 <= e1 && s2 <= e2){
if(array[s1] < array[s2]){
temp[k++] = array[s1++];
}else{
temp[k++] = array[s2++];
}
}
while(s1 <= e1){
temp[k++] = array[s1++];
}
while(s2 <= e2){
temp[k++] = array[s2++];
}
for (int i = 0; i < temp.length; i++) {
array[i+start] = temp[i];
}
}
基数排序是这样一种排序算法,我们可以从低位(个位)开始,根据个位数排序一次,然后根据十位数排序,再根据百位数进行排序……最终完成整个数组的排序。
对于十进制数字而言,每一位只会是 0~9 这十个数字,我们通常使用桶排序(计数排序)来完成每一位数的排序。桶排序是一种稳定的排序算法,基数排序的正确性依赖一种稳定的排序算法。
基数排序其实是分 LSD(从低位向高位排序) 和 MSD(从高位向低位排序) 两种。
public static void main(String[] args) {
int[] arr = new int[] {
321, 1234, 543, 324, 24, 960, 540, 672, 783, 1000 };
radixSort(arr);
printArray(arr);
}
public static void radixSort(int[] arr) {
int digit = getMaxDigit(arr); // 获取最大的数是多少位
for (int i = 0; i < digit; i++) {
bucketSort(arr, i); // 执行 digit 次 bucketSort 排序即可
}
}
public static int getMaxDigit(int[] arr) {
int digit = 1; // 默认只有一位
int base = 10; // 十进制每多一位,代表其值大了10倍
for (int i : arr) {
while (i > base) {
digit++;
base *= 10;
}
}
return digit;
}
public static void bucketSort(int[] arr, int digit) {
int base = (int) Math.pow(10, digit);
// init buckets
ArrayList<ArrayList<Integer>> buckets = new ArrayList<ArrayList<Integer>>();
for (int i = 0; i < 10; i++) {
// 只有0~9这十个数,所以准备十个桶
buckets.add(new ArrayList<Integer>());
}
// sort
for (int i : arr) {
int index = i / base % 10;
buckets.get(index).add(i);
}
// output: copy back to arr
int index = 0;
for (ArrayList<Integer> bucket : buckets) {
for (int i : bucket) {
arr[index++] = i;
}
}
}
public static void printArray(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}