基础的排序算法
时间:2021-07-29 16:19:56
收藏:0
阅读:0
简单梳理一下以前学过的排序算法
冒泡排序
平均时间复杂度:O(n2);稳定
- 比较相邻元素,如果前面的比后面大,就交换两个元素
- 每一对相邻元素做同样的比较,从开始第一对元素一直比到结尾,一轮结束最后的元素是最大的。
- 除了每轮比较出来的最大元素,对其他元素重复以上操作。
public void bubbleSort(int[] array) {
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length - 1; j++) {
if (array[j + 1] < array[j]) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
}
选择排序
平均时间复杂度:O(n2);不稳定
- 在所有元素中选取最小的元素,放在第一个位置。
- 在剩余元素里选取最小的元素,放在第二个位置。
- 以此类推
public void selectionSort(int[] array) {
for (int i = 0; i < array.length; i++) {
int minIndex = i;
for (int j = i; j < array.length; j++) {
if (array[j] < array[minIndex]) {
minIndex = j;
}
}
int temp = array[minIndex];
array[minIndex] = array[i];
array[i] = temp;
}
}
插入排序
平均时间复杂度:O(n2);稳定
- 以第一个元素为有序序列,从末尾开始比较,即要插入的元素和已经有序的最大者开始比起。
- 如果比它大则插入后面,否则一直比较,直到找到它该插入的位置。
- 如果遇到的元素和要插入的元素相等,那么要插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,所以插入排序是稳定的。
public void insertionSort(int[] array) {
int current;
for (int i = 0; i < array.length - 1; i++) {
current = array[i + 1];
int preIndex = i;
while (preIndex >= 0 && current < array[preIndex]){
array[preIndex + 1] = array[preIndex];
preIndex--;
}
array[preIndex + 1] = current;
}
}
希尔排序
平均时间复杂度:O(nlog?n);不稳定
希尔排序又叫做最小增量排序,将整个待排序的序列分割成为若干子序列,分别进行插入排序。
- 选择增量 gap=length/2,这种增量选择可以用一个序列来表示,{n/2, (n/2)/2, ... 1},称为增量序列。
- 对每个子序列进行插入排序后,缩小增量继续以 gap = gap/2 的方式执行。
public void 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;
}
}
归并排序
分治法的典型应用。始终都是 O(nlogn) 的时间复杂度,代价是需要额外的内存空间。
平均时间复杂度:O(nlogn);稳定
- 将长度为 n 的序列分成两个长度为 n/2 的子序列;
- 分别对子序列采用归并排序;
- 将两个排序好的子序列合并成一个有序序列;
public void sort(int[] array) {
//在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间
int[] temp = new int[array.length];
sort(array, 0, array.length - 1, temp);
}
public void sort(int[] array, int left, int right, int[] temp) {
if (left < right) {
int mid = (left + right) / 2;
sort(array, left, mid, temp); //左边归并排序,使得左子序列有序
sort(array, mid + 1, right, temp);//右边归并排序,使得右子序列有序
merge(array, left, mid, right, temp);//将两个有序子数组合并操作
}
}
public void merge(int[] array, int left, int mid, int right, int[] temp){
int i = left; //左序列指针
int j = mid + 1; //右序列指针
int t = 0; //临时数组指针
while (i <= mid && j <= right) {
if (array[i] <= array[j]) {
temp[t++] = array[i++];
} else {
temp[t++] = array[j++];
}
}
while (i <= mid) {//将左边剩余元素填充进temp中
temp[t++] = array[i++];
}
while (j <= right) {//将右序列剩余元素填充进temp中
temp[t++] = array[j++];
}
t = 0;
//将temp中的元素全部拷贝到原数组中
while (left <= right) {
array[left++] = temp[t++];
}
}
快速排序
平均时间复杂度:O(nlogn);不稳定
- 在序列中选一个基准数(pivot),一般选首位置元素为基准。
- 快排利用两个指针,分别设为左left,右right,双向进行。比基准数大的放右边,比基准数小的放左边,当left < right 时,遍历结束。
- 利用递归,把比基准小的子序列、比基准大的子序列分别重复上述排序步骤。
public void quickSort(int[] array, int left, int right) {
if (left < right) {
int index = getIndex(array, left, right);
quickSort(array, left, index - 1);
quickSort(array, index + 1, right);
}
}
public int getIndex(int[] array, int left, int right) {
int pivot = array[left];
while (left < right) {
while (left < right && array[right] >= pivot) {
right--;
}
array[left] = array[right];
while (left < right && array[left] <= pivot) {
left++;
}
array[right] = array[left];
}
array[right] = pivot;
return right;
}
public void quickSort(int[] array) {
quickSort(array, 0, array.length - 1);
}
堆排序
有点遗忘,回头补上
评论(0)