优化过的冒泡排序
冒泡排序是最简单的排序算法,通过重复交换相邻元素(如果它们的顺序错误)来工作。
public static void bubbleSort(int[] arr, int n)
{
int i, j;
boolean swapped;
for (i = n-1; i > 0; i--)
{
swapped = false;
for (j = 0; j < i; j++)
{
if (arr[j] > arr[j + 1])
{
swap(arr, j, j+1);
swapped = true;
}
}
if (!swapped)
{
break;
}
}
}
时间复杂度:O(n^2)
最好情况:O(n)
稳定性:稳定
选择排序
选择排序算法通过从未排序部分重复查找最小元素(考虑升序)并将其放在开头来对数组进行排序。
该算法在给定数组中维护两个子数组。
1)已经排序的子阵列。
2)未分类的剩余子阵列。
在选择排序的每次迭代中,挑选来自未排序子阵列的最小元素(考虑升序)并将其移动到排序的子阵列。
需要n-1次选择,第i次选择从arr[i…n-1]选择最小的元素放到位置i(左边的元素先达到有序状态)
void selectionSort(int arr[], int n)
{
int i, j, min_index;
for (i = 0; i < n - 1; i++)
{
min_index = i;
for (j = i + 1; j < n; j++)
{
if (arr[j] < arr[min_index])
{
min_index = j;
}
}
if (min_index != i)
{
swap(&arr[min_index], &arr[i]);
}
}
}
时间复杂度: O(n^2)
好处;
插入排序
插入排序是一种简单的排序算法,它的工作方式与我们手中的扑克牌排序方式相同,即将未排序部分的元素插入到已排序序列中。
从i = 1循环到n-1,选择元素arr [i]并将其插入到已排序序列arr [0 … i-1]中
void insertionSort(int arr[], int n)
{
int i, j, temp;
for (i = 1; i < n; i++)
{
temp = arr[i];
for (j = i - 1; j >= 0 && temp < arr[j]; j--)
{
arr[j + 1] = arr[j];
}
arr[j + 1] = temp;
}
}
Time Complexity: O(n*2)
Stable: Yes
Uses:适用于数组中元素基本有序且规模较小时
二分插入排序
我们可以使用二分搜索来减少正常插入排序中的比较次数。二分插入排序使用二分搜索来查找在每次迭代时插入所选项的正确位置。 在正常插入排序中,在最坏的情况下需要进行O(n)比较(在第n次迭代)。我们可以使用二分搜索将其减少到O(log n)。
int binarySearch(int arr[], int item, int low, int high)
{
if (low >= high)
{
return item > arr[low] ? low + 1 : low;
}
int mid = (low + high) / 2;
if (item == arr[mid])
{
return low + 1;
}
else if (item < arr[mid])
{
return binarySearch(arr, item, low, mid - 1);
}
else
{
return binarySearch(arr, item, mid + 1, high);
}
}
void binaryInsertionSort(int arr[], int n)
{
int i, j, key, loc;
for (i = 1; i < n; i++)
{
key = arr[i];
j = i - 1;
loc = binarySearch(arr, key, 0, j);
while (j >= loc)
{
arr[j + 1] = arr[j];
j--;
}
arr[loc] = key;
}
}
Time Complexity: The algorithm as a whole still has a running worst case running time of O(n2) because of the series of swaps required for each insertion.