冒泡排序
思路:
将当前元素与下一个元素比较,如果大于下一个元素则交换位置。这样最大的元素就会冒泡到最后一位。
对未排序部分重复这个过程。
// 时间复杂度 平均/最坏--O(n2) 最好--O(n)
// 空间复杂度--O(1)
// 稳定:不会交换相等元素的位置
void bubbleSort(int[] arr) {
int len = arr.length;
for (int i = 0; i < len - 1; i++) {
for (int j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
}
快速排序
思路:
以第一个元素为基准pivot,将数组分为两部分,左侧为<=pivot的元素,右侧为>pivot的元素,对两部分递归使用快速排序。
我们选取第一个元素作为基准。排序时先移动右指针,这样可以将需要交换的元素暂时存储在被当做基准的位置。
// 时间复杂度 最坏--O(n2) 平均/最好--O(nlogn)
// 空间复杂度--O(nlogn)
// 不稳定
void sort(int[] arr, int head, int tail) {//初始值为头和尾
//递归出口
if(head>=tail) {
return;
}
int pivot=arr[head]; //基准
int left=head;
int right=tail;
while(left<right){
//基准左边元素小于它,右边元素大于它
while(left<right&&arr[right]>pivot) {//右边元素小于基准停下
right--;
}
arr[left]=arr[right];
while(left<right&&arr[left]<=pivot) {//左边元素大于基准停下
left++;
}
arr[right]=arr[left];
//交换左右元素
}
//将基准放到中间
arr[left]=pivot;
sort(arr, head, left-1);
sort(arr, right+1, tail);
}
堆排序
思路:
堆是一个近似的完全二叉树,可以用数组存储。对于下标为i的结点,它的左孩子为2i+1,右孩子为2i+2。大顶堆中父节点大于子节点,小顶堆中父节点小于子节点。
我们首先构建一个大顶堆:对于每一个有孩子的结点,比较它与子节点的大小(先左后右),如果小于子节点,则进行交换。从最末一个有孩子的节点开始,直到根节点。
大顶堆的根结点是序列中最大的元素,我们将根节点与最末一个结点进行交换,则交换处前面为堆的无序部分,后面为堆的有序部分。我们对无序部分进行调整。
堆的调整用到了递归,将当前结点与子结点进行比较(先左后右),如果小于子节点则进行交换,然后再将结点值所在位置继续与它的子节点进行比较。递归出口为当前结点没有子节点或者不需要交换。
// 时间复杂度 最坏--O(n2) 平均/最好--O(nlogn)
// 空间复杂度--O(1)
// 不稳定
public class Heap {
public void buildHeap(int[] arr) { // 构建大顶堆
int len=arr.length;
for(int i=len/2-1;i>=0;i--) { // 2i+1<len或2i<len才有子节点
this.compare(arr, i, len);
}
}
public void heapSort(int arr[]) { //堆排序
this.buildHeap(arr);
int len=arr.length;
int templen=len;
for(int i=len-1;i>0;i--) { // 将根结点与无序部分的最后一个结点交换位置,然后调整新的无序堆
this.exchange(arr, 0, i);
templen--;
this.compare(arr, 0, templen);
}
}
public void exchange(int arr[], int i, int j) { //交换arr[i]与arr[j]
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
public void compare(int arr[], int i, int len) { //父节点小于子节点,交换,右孩子大于左孩子(先左后右)
int left=2*i+1;
int right=2*i+2;
int flag=0;
if(left<len&&arr[i]<arr[left]) { // left
this.exchange(arr, i, left);
flag=left;
}
if(right<len&&arr[i]<arr[right]) { // right
this.exchange(arr, i, right);
flag=right;
}
if(flag!=0) {
compare(arr, flag, len);
}
}
}