- 冒泡排序
- 插入排序
- 选择排序
- 归并排序
- 快速排序
- 希尔排序
- 堆排序
- 基数排序
冒泡排序
对于给定的 n 个数据,每次选择相邻的两个数据进行比较,将数值较大的数据放在后面。
- 第一次比较:将数值的最大的数据排在最后面;
- 第二次比较:将数值次大的数据排在倒数第二;
- 经过 n 次比较后:最小值将排在第一位。
private static void bubbleSort(int[] arr){
for(int i=0;i<arr.length;i++){ //遍历所有数据,比较n次。
for(int j=0;j<arr.length-i-1;j++) { // 相邻数据两两比较;
if(arr[j+1]<arr[j]){
int tmp = arr[j];
arr[j] =arr[j+1];
arr[j+1] = tmp;
}
}
}
}
插入排序
设有一个有序的初始序列,然后从原记录中取出一个数据,依次与初始有序序列中的数据进行比较,最后将数据插入到指定的位置。
- 从原数组中取出第一个位置的数据,作为初始有序序列;
- 从原数据中的第二个位置开始依次取出一条数据,与初始有序序列中的数据进行比较,并将数据插入到初始有序序列中的指定位置;
private static void insertSort(int[] arr) {
int insertVal = 0;
int insertIndex = 0;
for (int i = 1; i < arr.length; i++) { // 从原数组的第二个数据开始依次取出一个数据;
insertVal = arr[i]; // 取出来的数据
insertIndex = i - 1; // 记录索引位置,取出数据的当前位置的前一个位置索引。其实记录着初始有序序列的长度
// 遍历初始数据,将取出来的数据与初始数组依次比,由于初始数据是有序的
// 因此将初始数组中的大于取出来的数据值的数据往后移动一位。
while (insertIndex >= 0 && insertVal < arr[insertIndex]) {
arr[insertIndex + 1] = arr[insertIndex];
insertIndex--;
}
// 将取出来的数据插入到初始数值中。
if (insertIndex + 1 != i) {
arr[insertIndex + 1] = insertVal;
}
}
}
选择排序
依次从数组中取出一个数据,然后依次与其索引之后的数据进行比较,如果不满足要求,即进行交换。
- 取出索引为 0 的数据,与之后的数据一一进行比较,将最小的数据放在当前索引 0 的位置;
- 取出所因为 1 的数据,与之后的数据一一进行比较,然后将次小的数据放在当前索引 1 的位置;
- 依次取出比较,最终得到一个有序数组。
private static void selectSort(int[] arr){
for(int i=0;i<arr.length;i++){
int minInde = i; // 获取当前索引位置
int min = arr[minInde]; // 获取当前索引位置的数据
for(int j= i;j<arr.length;j++){ // 分别与索引之后的数据进行比较
if(arr[j] < min){ // 两两比较找出最小值
min = arr[j];
minInde = j; // 找出两两比较后较小值的索引位置
}
}
// 交换
arr[minInde] = arr[i];
arr[i]= min;
}
}
归并排序
利用递归与分而治之的思路将数组切分成一系列很小很小的半子表,当半子表完成排序后再合并在一定,最终形成一个有序的数组。
- 将数组进行拆分成很短的序列数组;
- 然后依次比较合并;
private static void mergeSort(int[] arr, int left, int right, int[] tmp) {
if (left < right) {
int mid = (left + right) / 2;
mergeSort(arr, left, mid, tmp); // 上半子表拆分,不能再拆执行 merge
mergeSort(arr, mid + 1, right, tmp); // 下半子表拆分,不能再拆执行 merge
merge(arr, left, mid, right, tmp);
}
}
private static void merge(int[] arr, int left, int mid, int right, int[] tmp) {
int i = left;
int j = mid + 1;
int t = 0;
while (i <= mid && j <= right) {
if (arr[i] <= arr[j]) {
tmp[t] = arr[i];
t += 1;
i += 1;
} else {
tmp[t] = arr[j];
t += 1;
j += 1;
}
}
while (i <= mid) {
tmp[t] = arr[i];
t += 1;
i += 1;
}
while (j <= right) {
tmp[t] = arr[j];
t += 1;
j += 1;
}
t = 0;
int tmpIndex = left;
while (tmpIndex <= right) {
arr[tmpIndex] = tmp[t];
t += 1;
tmpIndex += 1;
}
}
快速排序
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小。然后再按此方法对这两部分数据分别进行快速排序。整个排序过程可以递归进行。以此达到整个数据数组的有序。
private static void quickSort(int[] arr, int left, int right) {
int l = left;
int r = right;
int m = (left + right) /2;
int pivot = arr[m];
while(l < r){
while(arr[l] < pivot){
l++;
}
while(pivot < arr[r]){
r--;
}
if(l >= r){
break;
}
int tmp = arr[l];
arr[l] = arr[r];
arr[r] = tmp;
if(arr[l] == pivot){
r--;
}
if(arr[r] == pivot){
l++;
}
}
if(l == r){
l++;
r--;
}
if(left < r){
quickSort(arr,left,r);
}
if(l <right){
quickSort(arr,l,right);
}
}
希尔排序
把记录按下标的一定增量分组,对每组使用直接插入排序算法排序。随着增量逐渐减少,每组包含的关键词越来越多,当增量减少至 1 时,整个文件恰好是有序的。
private static void shellSort(int[] arr) {
for (int gap = arr.length / 2; gap > 0; gap /= 2) {
for (int j = gap; j < arr.length; j++) {
for (int k = j - gap; k >= 0; k -= gap) {
if (arr[k] > arr[k + gap]) {
int tmp = arr[k];
arr[k] = arr[k + gap];
arr[k + gap] = tmp;
}
}
}
}
}
堆排序
堆排序是一种选择排序,是一种不稳定排序。
- 将待排数组构造成一个大顶堆
- 此时整个序列的最大值就是堆顶的根节点
- 将其与末尾元素交换,末尾就是最大值。
- 对余下数据重复上述操作,最终得到一个有序数组。
private static void heapSort(int[] arr) {
// 将数组构建成大顶堆
for (int i = arr.length /2 -1 ; i >= 0; i--) {
adjustHeap(arr, i, arr.length);
}
// 始终将栈顶元素与栈顶元素进行交换,保证数组末尾始终是最大值
for (int j = arr.length - 1; j > 0; j--) {
int tmp = arr[j];
arr[j] = arr[0];
arr[0] = tmp;
adjustHeap(arr, 0, j);
}
}
// 构建大堆顶
private static void adjustHeap(int[] arr, int i, int length) {
int tmp = arr[i];
// 2*i+1 是左节点
for (int k = i * 2 + 1; k < length; k = k * 2 + 1) {
if (k + 1 < length && arr[k] < arr[k + 1]) {
// k += 1 是右子节点
k++;
}
// 子根节点与左右子树节点进行比较
if (arr[k] > tmp) {
arr[i] = arr[k];
i = k;
} else {
break;
}
}
arr[i] = tmp;
}
基数排序
将所有待比较数值统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序,这样从最低位排序一直到最高位排序完成后,数组将会变成一个有序序列。
private static void radixSort(int[] arr){
int max = arr[0];
for(int i = 1; i< arr.length;i++){
if(arr[i] > max){
max = arr[i];
}
}
int maxLength = (max+"").length();
int[][] bucket = new int[10][arr.length];
int [] bucketElementCounts = new int[10];
for(int i=0,n =1;i<maxLength;i++,n*=10){
for(int j = 0;j<arr.length;j++){
int digitOfElement = arr[j]/n %10;
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
bucketElementCounts[digitOfElement]++;
}
int index = 0;
for(int k = 0;k<bucketElementCounts.length;k++){
if(bucketElementCounts[k] != 0){
for(int l =0;l<bucketElementCounts[k];l++) {
arr[index++] = bucket[k][l];
}
}
bucketElementCounts[k] = 0;
}
}
}