转自:https://www.cnblogs.com/0201zcr/p/4763806.html
冒泡算法:一次遍历找到剩余无序元素的最值放到最后,交换完成位移。
(时间平均复杂度:O(n2))
public static void bubbleSort(int[] numbers)
{
int temp;
int size = numbers.length;
for(int i = 0 ; i < size-1; i ++)
{
for(int j = 0 ;j < size-1-i ; j++)
{
if(numbers[j] > numbers[j+1]) //交换两数位置
{
temp = numbers[j];
numbers[j] = numbers[j+1];
numbers[j+1] = temp;
}
}
}
}
快速排序:关键字:中数、轮循赋值、中数赋值;
(时间平均复杂度:O(nlog2n))
public static void quickSort(int[] numbers, int low, int high) {
if (low < high) {
int middle = getMiddleIndex(numbers, low, high);
quickSort(numbers, low, middle - 1);
quickSort(numbers, middle + 1, high);
}
System.out.println(Arrays.toString(numbers));
}
public static int getMiddleIndex(int[] numbers, int low, int high) {
int middle = numbers[low];
while (low < high) {
while (low < high && numbers[high] > middle)
high--;
numbers[low] = numbers[high];
while (low < high && numbers[low] < middle)
low++;
numbers[high] = numbers[low];
}
numbers[low] = middle;//记得返回中数下标前给中数赋值
return low;
}
选择排序:一次遍历找到剩余无序元素的最值放到最前,但不是通过交换实现位移,而是通过记录下标,最后才交换一次。
(时间平均复杂度:O(n2))
public static void selectSort(int[] numbers) {
int length = numbers.length;
int temp;
for (int i = 0; i < length; i++) {
int k = i;//最小值下标
for (int j = i; j < length; j++) {
if(numbers[k] > numbers[j])
k = j;
}
temp = numbers[k];
numbers[k] = numbers[i];
numbers[i] = temp;
}
System.out.println(Arrays.toString(numbers));
}
插入排序:数组分两段,前面的是排好序的。后面一段,拿第一个出来,排好序的一段找到合适的位置插入。
(时间平均复杂度:O(n2))
public static void insertSort(int[] numbers)
{
int size = numbers.length;
int temp;
for(int i = 0 ; i < size ; i++)
{
temp = numbers[i];
int j;
//假如temp比前面的值小,则将前面的值后移
for(j = i ; j > 0 ; j --)
{
if(numbers[j-1] > temp)
numbers[j] = numbers[j-1];//后移
else
break;
}
numbers[j] = temp;//因为是j--出来的
}
System.out.println(Arrays.toString(numbers));
}
希尔排序:若干个插入排序得到的。当遍历到最后increment=1时,则为插入排序。
(时间平均复杂度:O(n1.3))
public static void shellSort(int[] data) {
int j = 0;
int temp = 0;
//每次将步长缩短为原来的一半
for (int increment = data.length / 2; increment > 0; increment /= 2){
for (int i = increment; i < data.length; i++) {
temp = data[i];
for (j = i; j >= increment; j -= increment) {
if(temp < data[j - increment]){
data[j] = data[j - increment];
}else{
break;
}
}
data[j] = temp;
}
}
}
归并排序:两段有序子序列,分别拿出第一个元素,小的放到新有序序列中。被放元素的子序列继续拿,继续比较。
说明:当向下递归到左右序列的长度都不超过2的时候,merge之后的合并序列就是有序的,所以递归往上走都是有序的。
关键字:左右指针
(时间平均复杂度:O(nlog2n))
public static int[] sort(int[] nums, int low, int high) {
int mid = (low + high) / 2;
if (low < high) {
sort(nums, low, mid);// 左边
sort(nums, mid + 1, high);// 右边
merge(nums, low, mid, high);// 左右归并
}
return nums;
}
private static void merge(int[] numbers, int low, int middle, int high) {
int[] temp = new int[high - low + 1];
int i = low, j = middle + 1, k = 0;//i左指针,j右指针,k新数组下标
while (i <= middle && j <= high) //轮循把小的元素放到新数组中
temp[k++] = numbers[i] < numbers[j] ? numbers[i++] : numbers[j++];
while (i <= middle)// 把左边剩余的数移入数组
temp[k++] = numbers[i++];
while (j <= high)// 把右边剩余的数移入数组
temp[k++] = numbers[j++];
System.arraycopy(temp, 0, numbers, low, temp.length);// 把新数组中的数覆盖numbers数组
}
堆排序:把数组的元素看成二叉树上的结点。从最后一个非叶子节点开始,每次比较并交换后,父节点会比其子节点的值大。这样一轮循环后,最大值肯定不在最后下面一层。以此类推,最大值会跑到最上面(根节点)。然后把最大值(index=0)和数组最后一个交换,并把除了最大值的数组当做新数组,继续上述步骤。
(时间平均复杂度:O(nlog2n))
public static void main(String[] args) {
int[] a = {2, 53, 25, 78, 9, 87, 47, 1, 28, 81, 19, 77};
int arrayLength=a.length;
//循环建堆
for(int i=0;i<arrayLength-1;i++){
//建堆
buildMaxHeap(a,arrayLength-1-i);
//交换堆顶和最后一个元素
swap(a,0,arrayLength-1-i);
System.out.println(Arrays.toString(a));
}
}
//对data数组从0到lastIndex建大顶堆
public static void buildMaxHeap(int[] data, int lastIndex){
//从lastIndex处节点(最后一个节点)的父节点开始
for(int i=(lastIndex-1)/2;i>=0;i--){
//k保存正在判断的节点
int k=i;
//如果当前k节点的子节点存在
while(k*2+1<=lastIndex){
//k节点的左子节点的索引
int biggerIndex=2*k+1;
//如果biggerIndex小于lastIndex,即biggerIndex+1代表的k节点的右子节点存在
if(biggerIndex<lastIndex){
//若果右子节点的值较大
if(data[biggerIndex]<data[biggerIndex+1]){
//biggerIndex总是记录较大子节点的索引
biggerIndex++;
}
}
//如果k节点的值小于其较大的子节点的值
if(data[k]<data[biggerIndex]){
//交换他们
swap(data,k,biggerIndex);
//将biggerIndex赋予k,开始while循环的下一次循环,重新保证k节点的值大于其左右子节点的值
k=biggerIndex;
}else{
break;
}
}
}
}
//交换
private static void swap(int[] data, int i, int j) {
int tmp=data[i];
data[i]=data[j];
data[j]=tmp;
}