排序算法的java实现
直接插入排序
public static void insertSort(int arr[]){
int tmp, i, j;
for (i = 1; i < arr.length; i++){
tmp = arr[i];
j = i - 1;
while (j >= 0 && tmp < arr[j]){
arr[j+1] = arr[j];
j--;
}
arr[j+1] = tmp;
}
}
简单选择排序
public static void selectSort(int arr[]){
for (int i = 0; i < arr.length - 1; i++){
int k = i; //记录本轮最小值的下标
for (int j = i+1; j < arr.length; j++){
if (arr[j] < arr[k]){
k = j;
}
}
if (k != i){
//交换最小值与当前无序序列的第一个关键字
int tmp = arr[i];
arr[i] = arr[k];
arr[k] = tmp;
}
}
}
冒泡排序
public static void bubbleSort(int arr[]){
for(int i = arr.length-1; i >= 1; i--){ // arr.length-1轮交换
int flag = 0; // 标记本轮是否有交换,0表示未交换,1表示交换
for (int j = 0; j < i; j++){
if (arr[j] > arr[j+1]){
int tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
flag = 1; // 本轮发生了交换
}
}
if (flag == 0){
break; // 若本轮未发生交换排序结束
}
}
}
希尔排序
public static void shellSort(int arr[]){
for (int step = arr.length/2; step >= 1; step/=2){
for (int i = step;i<arr.length;i+=step){
for (int j = i; j>0;j-=step){
if (arr[j]<arr[j-step]){
int tmp = arr[j];
arr[j] = arr[j-step];
arr[j-step] = tmp;
}
}
}
}
}
快速排序
快速排序思路:
- 选取第一个关键字作为枢轴 (pivot)
- 一次划分过程,将比pivot小的关键字交换到前面,比pivot大的关键字交换到后面
- 对划分后的左右区间重复第二步,直到各区间只有一个数
一次划分过程
public static int partition(int arr[], int startIndex, int endIndex){
// 划分
int low = startIndex;
int high = endIndex;
int pivotKey = arr[low];
while (low < high){
while (low < high && arr[high] >= pivotKey){ // 从右往左扫描
high--; // 找到第一个小于pivotKey的关键字
}
if (low < high){
arr[low] = arr[high];
}
while (low < high && arr[low] < pivotKey){ // 从左往右扫描
low++; // // 找到第一个大于pivotKey的关键字
}
if (low < high){
arr[high] = arr[low];
}
}
arr[low] = pivotKey;
return low; // 返回pivotKey所在位置
}
public static void quickSort(int arr[], int startIndex, int endIndex){
if (endIndex <= startIndex) {
return;
}
int pivotIndex = partition(arr, startIndex, endIndex);
quickSort(arr, startIndex, pivotIndex-1);
quickSort(arr, pivotIndex+1, endIndex);
}
堆排序
- 完全二叉树的顺序存储结构
-
大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列;
-
小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列;
-
构建堆
- 输出堆顶元素并调整新堆
-
堆排序算法
- 构建初始堆,将待排序列构成一个大顶堆(或者小顶堆),升序大顶堆,降序小顶堆; 将堆顶元素与堆尾元素交换,并断开(从待排序列中移除)堆尾元素。
- 重新构建堆。
- 重复2~3,直到待排序列中只剩下一个元素(堆顶元素)。
public static void adjustHeap(int arr[], int parent, int length){ // 调整为小顶堆 int tmp = arr[parent]; int lchild = 2 * parent + 1; // 指向左孩子 while (lchild < length) { // 若右孩子存在且更小,指向右孩子 if (lchild + 1 < length && arr[lchild] > arr[lchild + 1]){ lchild ++; } // 如果父结点的值小于最小孩子结点的值,则直接结束 if (tmp <= arr[lchild]){ break; } arr[parent] = arr[lchild]; parent = lchild; lchild = 2 * lchild + 1; } arr[parent] = tmp; } public static void heapSort(int arr[]){ // 实现降序排序 //1. 创建小顶堆 for(int i = arr.length/2-1; i >= 0; --i){ // 从最后一个非叶节点向前筛选 adjustHeap(arr, i, arr.length); } // 2. 输出堆顶元素并调整新堆 for (int i = arr.length - 1; i > 0; i--) { //将堆顶元素与末尾元素进行交换 int temp = arr[i]; arr[i] = arr[0]; arr[0] = temp; //重新对堆进行调整 adjustHeap(arr, 0, i); } }
二路归并排序
public static void merge(int[] arr, int low, int mid, int high){
// merge arr[low],...,arr[mid] 及 arr[mid+1], ..., arr[high]
int n1 = mid - low + 1; // 第一个子表的关键字个数
int n2 = high - mid; // 第二个子表的关键字个数
int[] L = new int[n1]; // 存储第一个子表的关键字
int[] R = new int[n2]; // 存储第二个子表的关键字
for (int i = 0; i < n1; i++){
L[i] = arr[low + i];
}
for (int j = 0; j < n2; j++){
R[j] = arr[mid + 1 + j];
}
int i = 0;
int j = 0;
int k = low;
while (i < n1 && j < n2){ // merge
if (L[i] < R[j]){
arr[k++] = L[i++];
}
else{
arr[k++] = R[j++];
}
}
while (i < n1){
arr[k++] = L[i++];
}
while (j < n2){
arr[k++] = R[j++];
}
}
public static void mergeSort(int[] arr, int low, int high){
if (low >= high){
return;
}
int mid = (low + high)/2;
mergeSort(arr, low, mid); // 排序左子表
mergeSort(arr, mid+1, high); // 排序右子表
merge (arr, low, mid, high); // 归并操作
}