Bootstrap

Java数据结构-排序


前言

这里的博客主要是想将学习的排序算法的代码复习记录一下。
在这里插入图片描述

一、插入排序

//插入排序
public void insertSort(int[] arr) {
    for (int i = 1; i < arr.length; i++) {
        int temp = arr[i];
        int j = i - 1;
        for (; j >= 0; j--) {
            if (temp < arr[j]) {
                arr[j + 1] = arr[j];
            } else {
                break;
            }
        }
        arr[j + 1] = temp;
    }
}

二、希尔排序

public void shellSort(int[] arr) {
    int gap = arr.length;
    while (gap > 1) {
        gap /= 2;
        shell(arr, gap);
    }
}
public void shell(int[] arr, int gap) {
    for (int i = gap; i < arr.length; i ++) {
        int temp = arr[i];
        int j = i - gap;
        for (; j >= 0; j -= gap) {
            if (arr[j] > temp) {
                arr[j + gap] = arr[j];
            } else {
                break;
            }
        }
        arr[gap + j] = temp;
    }
}

三、选择排序

//选择排序
public void selectSort(int[] arr) {
    for (int i = 0; i < arr.length; i++) {
        int min = i;
        for (int j = i + 1; j < arr.length; j++) {
            if (arr[j] < arr[i]) {
                min = j;
            }
        }
        swap(arr, i, min);
    }
}

public void swap(int[] arr, int i, int j) {
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

四、堆排序

public void headSort(int[] arr) {
    createHeap(arr);
    int end = arr.length - 1;
    while (end > 0) {
        swap(arr, 0, end);
        siftDown(arr, 0, end);
        end--;
    }
}
public void createHeap(int[] arr) {
    for (int i = (arr.length - 2) / 2; i >= 0; i--) {
        siftDown(arr, i, arr.length);
    }
}
public void siftDown(int[] arr, int parent, int end) {
    int child = 2 * parent + 1;
    while (child < end) {
        if (child + 1 < end && arr[child] < arr[child + 1])
            child++;
        }
        if (arr[child] > arr[parent]) {
            swap(arr, child, parent);
            parent = child;
            child = parent * 2 + 1;
        }
    }
}

五、冒泡排序

public void bubbleSort(int[] arr) {
    for (int i = 0; i < arr.length - 1; i++) {
        boolean flg = true;
        for (int j = 0; j < arr.length - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                flg = false;
                swap(arr, j, j + 1);
            }
        }
        if (flg) {
            return ;
        }
    }
}

六、快速排序

递归方法:

//快排
public void quickSort(int[] arr) {
    quick(arr, 0, arr.length - 1);
}

public void quick(int[] arr, int start, int end) {
    if (start >= end) {
        return;
    }
    //这里用到了插入排序,因为插入排序在待排序数据接近有序时,排序速度比较快
    //当快排达到以下条件时说明数据已经快接近有序了,这是就可以直接使用插入排序来提升速度
    if (end - start + 1 < 10) {
        insertSortForQ(arr, start, end);
        return;
    }
    //这里是将start、end以及它们的中位数mid指向的元素进行比较选出中间值作为基准进行快排
    //这样可以使排序结构尽量接近二叉树从而提高排序效率
    int index = getMidNumIndex(arr, start, end);
    swap(arr, index, start);
    int pivot = partition(arr, start, end);
    quick(arr, start, pivot - 1);
    quick(arr, pivot + 1, end);
}

public void insertSortForQ(int[] arr, int start, int end) {
    for (int i = start + 1; i <= end; i++) {
        int temp = arr[i];
        int j = i - 1;
        for (; j >= start; j--) {
            if (arr[j] > temp) {
                arr[j + 1] = arr[j];
            } else {
                break;
            }
        }
        arr[j + 1] = temp;
    }

}
//partition函数分为两种,这种为填坑法
public int partition(int[] arr, int left, int right) {
    int temp = arr[left];
    while (left < right) {
        while (right > left && arr[right] >= temp) {
            right--;
        }
        arr[left] = arr[right];
        while (left < right && arr[left] <= temp) {
            left++;
        }
        arr[right] = arr[left];
    }
    arr[left] = temp;
    return left;
}
//另一种为Hoare法
    public int partitionHoare(int[] arr, int left, int right) {
    int temp = arr[left];
    while (left < right) {
        while (left < right && arr[right] >= temp) {
            right--;
        }
        while (left < right && arr[left] <= temp) {
            left++;
        }
        swap(arr, left, right);
    }
    swap(arr, 0, left);
    return left;
}

public int getMidNumIndex(int[] arr, int left, int right) {
    int mid = (right - left) / 2 + left;
    if (arr[left] > arr[right]) {
        if (arr[mid] > arr[left]) {
            return left;
        } else if (arr[mid] < arr[right]) {
            return right;
        } else {
            return mid;
        }
    } else {
        if (arr[mid] > arr[right]) {
            return right;
        } else if (arr[mid] < arr[left]) {
            return left;
        } else {
            return mid;
        }
    }

}

非递归方法:

//快排非递归
public void quickSortNor(int[] arr) {
    Stack<Integer> stack = new Stack<>();
    int left = 0;
    int right = arr.length - 1;
    int pivot = partition(arr, left, right);
    if (pivot - 1 > left) {
        stack.push(left);
        stack.push(pivot - 1);
    }
    if (right > pivot + 1) {
        stack.push(pivot + 1);
        stack.push(right);
    }
    while (!stack.isEmpty()) {
        right = stack.pop();
        left = stack.pop();
        pivot = partition(arr, left, right);
        if (pivot - 1 > left) {
            stack.push(left);
            stack.push(pivot - 1);
        }
        if (right > pivot + 1) {
            stack.push(pivot + 1);
            stack.push(right);
        }
    }
}

七、归并排序

递归方法:

//归并排序
public void mergeSort(int[] arr) {
    merge(arr, 0, arr.length - 1);
}

public void merge(int[] arr, int start, int end) {
    if (start >= end) {
        return;
    }
    int mid = (end - start) / 2 + start;
    merge(arr, start, mid);
    merge(arr, mid + 1, end);
    mergeFunc(arr, start, end, mid);
}

public void mergeFunc(int[] arr, int start, int end, int mid) {
    int s1 = start;
    int s2 = mid + 1;
    int e1 = mid;
    int e2 = end;
    int[] newArr = new int[end - start + 1];
    int index = 0;
    while (s1 <= e1 && s2 <= e2) {
        if (arr[s1] < arr[s2]) {
            newArr[index] = arr[s1];
            s1++;
            index++;

        } else {
            newArr[index] = arr[s2];
            s2++;
            index++;
        }
    }

    while (s1 <= e1) {
        newArr[index] = arr[s1];
        s1++;
        index++;
    }

    while (s2 <= e2) {
        newArr[index] = arr[s2];
        s2++;
        index++;
    }

    for (int i = 0; i < newArr.length; i++) {
        arr[start + i] = newArr[i];
    }

}

非递归方法:

public void mergeSortNor(int[] arr) {
   int gap = 1;
   while (gap < arr.length) {
       for (int i = 0; i < arr.length; i += 2 * gap) {
           int left = i;
           int mid = left + gap - 1;
           if (mid >= arr.length) {
               mid = arr.length - 1;
           }
           int right = mid + gap;
           if (right >= arr.length) {
               right = arr.length - 1;
           }
           mergeFunc(arr, left, right, mid);
       }
       gap *= 2;
   }
}

八、计数排序

//计数排序
public void countSort(int[] arr) {
    int max = arr[0];
    int min = arr[0];

    for (int i = 1; i < arr.length; i++) {
        if (arr[i] < min) {
            min = arr[i];
        }

        if (arr[i] > max) {
            max = arr[i];
        }
    }

    int[] newArr = new int[max - min + 1];
    for (int i = 0; i < arr.length; i++) {
        newArr[arr[i] - min] += 1;
    }

    int index = 0;
    for (int i = 0; i < newArr.length; i++) {
        int temp = newArr[i];
        while (temp != 0) {
            arr[index] = i + min;
            index++;
            temp--;
        }
    }
}
;