1.快排
快速排序会牺牲数组中的一个数据,所以实际的数组长度,会比真实的数据多一,其中会将下面所说的标志位赋值给arr[0]。以牺牲数组中arr[0]为例:
快速排序主要思想:在数组角标从left到right之间,取左边第一个数作为标志位,将标志位赋值给arr[0],然后分两步循环判断(这两步顺序不能混乱)1.从右至左,2.从左至右
1.从右至左:循环判断各个位与标志位的大小,当标志位大于当前位时结束循环,然后将当前放到数组的左边,即当前的left的位置上(arr[left])然后
(第一次循环放置在标志位的位置上,覆盖了标志位,但是arr[0]还是标志位没有被真正的覆盖,这样,在之后的转移覆盖的时候,就相当于出现了一个temp)
2.从左至右:循环判断各个位于标志位的大小,当标志位小于当前位时结束循环,然后将当前放到数组的右边,即当前的right的位置上(arr[right])
1.2.只是执行了一步,即只转换的了至多两个数字,所以外层必须再有一层循环,最后将arr[0]赋值给left。
再说递归问题,,上面说了快排是从left到right之间的问题,最后将标志位放置在中间的合理位置(即标志位的左边小于它,标志位的右边大于它)这样可以将数组一分为二
分别计算两边的数组,递归在这里很实用,
你要是知道打断点,然后DEBUG运行就更好了,可以很清楚的看见堆栈的信息,更方便理解
package day06;
public class ceshi2 {
public static void main(String[] args) { //快速排序
int[] arr = {0, 49, 38, 65, 97, 76, 13, 27, 49};
for (int i = 1; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
Quick(arr, 1, arr.length - 1);
for (int i = 1; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
private static void Quick(int[] arr, int left, int right) {
if (left < right) { //l
int i = Pisiton(arr, left, right);
Quick(arr, left, i - 1);
Quick(arr, i + 1, right);
}
}
private static int Pisiton(int[] arr, int left, int right) { //返回的是标志位的最后的位置
arr[0] = arr[left];
while (left < right) {
while (left < right && arr[right] >= arr[0]) right--; //从右至左,找到第一个小于标志位的数
if (left < right) { //将那个数放到左边
arr[left] = arr[right];
left++;
}
while (left < right && arr[left] < arr[0]) left++; //从左至右,找到第一个大于标志位的数
if (left < right) { //将那个数放到右边
arr[right] = arr[left];
right--;
}
}
arr[left] = arr[0]; //该次遍历的arr[left]赋值arr[0],即:最后将标志位放到合适的位置 左 < 标志位 <右
return left;
}
}
偷过来的一张图(咳咳,才没有盗,)
快速排序的趟数取决于数的高度
2.希尔排序
public static int[] ShellSort(int[] array) {
int len = array.length;
int temp, gap = len / 2;
while (gap > 0) {
for (int i = gap; i < len; i++) {
temp = array[i];
int preIndex = i - gap;
while (preIndex >= 0 && array[preIndex] > temp) {
array[preIndex + gap] = array[preIndex];
preIndex -= gap;
}
array[preIndex + gap] = temp;
}
gap /= 2;
}
return array;
}
3.简单选择排序
int[] arr = {49, 38, 65, 97, 76, 13, 27, 49};
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
for (int i = 0; i < arr.length; i++) {
int index = i;
int min = arr[i];
for (int j = i; j < arr.length; j++) {
if (min > arr[j]) {
index = j;
min = arr[j];
}
}
if (index != i) {
int temp = arr[index];
arr[index] = arr[i];
arr[i] = temp;
}
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
4.直接插入排序
int[] arr = {0, 38, 65, 97, 76, 13, 27, 49};
int i, j;
for ( i=2;i<arr.length;i++){
if(arr[i]<arr[i-1]){
arr[0]=arr[i];
for ( j=i-1;arr[0]<arr[j];j--){
arr[j+1]=arr[j];
}
arr[j+1]=arr[0];
}
}
for ( i=1;i<arr.length;i++) System.out.print(arr[i]+" ");
}
5.堆排序
//堆排序
public static void heapSort(int[] arr) {
//构造大根堆
heapInsert(arr);
int size = arr.length;
while (size > 1) {
//固定最大值
swap(arr, 0, size - 1);
size--;
//构造大根堆
heapify(arr, 0, size);
}
}
//构造大根堆(通过新插入的数上升)
public static void heapInsert(int[] arr) {
for (int i = 0; i < arr.length; i++) {
//当前插入的索引
int currentIndex = i;
//父结点索引
int fatherIndex = (currentIndex - 1) / 2;
//如果当前插入的值大于其父结点的值,则交换值,并且将索引指向父结点
//然后继续和上面的父结点值比较,直到不大于父结点,则退出循环
while (arr[currentIndex] > arr[fatherIndex]) {
//交换当前结点与父结点的值
swap(arr, currentIndex, fatherIndex);
//将当前索引指向父索引
currentIndex = fatherIndex;
//重新计算当前索引的父索引
fatherIndex = (currentIndex - 1) / 2;
}
}
}
//将剩余的数构造成大根堆(通过顶端的数下降)
public static void heapify(int[] arr, int index, int size) {
int left = 2 * index + 1;
int right = 2 * index + 2;
while (left < size) {
int largestIndex;
//判断孩子中较大的值的索引(要确保右孩子在size范围之内)
if (arr[left] < arr[right] && right < size) {
largestIndex = right;
} else {
largestIndex = left;
}
//比较父结点的值与孩子中较大的值,并确定最大值的索引
if (arr[index] > arr[largestIndex]) {
largestIndex = index;
}
//如果父结点索引是最大值的索引,那已经是大根堆了,则退出循环
if (index == largestIndex) {
break;
}
//父结点不是最大值,与孩子中较大的值交换
swap(arr, largestIndex, index);
//将索引指向孩子中较大的值的索引
index = largestIndex;
//重新计算交换之后的孩子的索引
left = 2 * index + 1;
right = 2 * index + 2;
}
}
//交换数组中两个元素的值
public static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}