插入排序,Insertion Sort.
给出伪代码
for i = 1,2,...,n-1
Insert A[i] into Sorted array A[0:i-1]
by swaping down to the correct position.
冒泡排序
冒泡排序就是一种插入排序算法。
i ← 1
while i < length(A)
j ← i
while j > 0 and A[j-1] > A[j]
swap A[j] and A[j-1]
j ← j - 1
end while
i ← i + 1
end while
冒泡排序的时间复杂度为O(n^2)
二分插入排序
对于如何找到正确的位置the correct position,由于A[0:i-1]是已经排序的数组,因此可以对A[0:i-1]进行二分搜索,找到刚好小于A[i]的元素A[j],暂存给一个变量num,再将A[j+1:i-1]整体后移一位,最后将num赋值给A[j]。
但是使用二分插入排序的平均时间复杂度依然是O(n^2),因为每次找到正确的位置,可能需要移动许多的元素。其实效率并不比冒泡快多少。
插入排序的空间复杂度为O(1),是一种就地(in-place)的算法。
并归排序
Merge Sort
算法思路:将一个未排序的大小为n的数组A,分为两个大小相似(n/2)的数组L和R;分别对这两个数组进行排序,排序后的数组分别为L'和R';再将L'和R'合并为已排序的数组A'。
我们可以通过画递归树或者使用主定理计算改算法的渐进时间复杂度。
C++实现归并排序的代码
class Solution {
public:
vector<int> sortedA;
vector<int> sortArray(vector<int>& nums) {
sortedA.resize(nums.size());
mergeSort(nums, 0, nums.size()-1);
return nums;
}
void mergeSort(vector<int>& nums, int left, int right)
{//merge sort
//take the array A apart into array L = A[0:n/2] and array R = A[n/2+1:n-1]
//sort the array L and R
//merge them together into the sorted array A'
if(left >= right)
{
return;
}
int mid = ((right-left) >> 1) + left;
mergeSort(nums, left, mid);
mergeSort(nums, mid+1, right);
mergeTwoSortedArray(nums, sortedA, left, mid, right);
}
void mergeTwoSortedArray(vector<int>& nums, vector<int>& sortedA, int left, int mid, int right)
{//合并两个已排序的数组
//int size = nums.size();
//array L = nums[left:mid]
//array R = nums[mid+1:right]
int i = left;
int j = mid+1;
int count = 0;
while(i <= mid && j <= right)
{
if(nums[i] < nums[j])
{
sortedA[count] = nums[i];
++count;
++i;
}
else if(nums[i] == nums[j])
{
sortedA[count] = nums[i];
++count;
sortedA[count] = nums[j];
++count;
++i;
++j;
}
else
{
sortedA[count] = nums[j];
++count;
++j;
}
}
while(j <= right)
{
sortedA[count] = nums[j];
count++;
++j;
}
while(i <= mid)
{
sortedA[count] = nums[i];
++count;
++i;
}
for(int i = 0;i < right - left + 1;++i)
{
nums[i+left] = sortedA[i];
}
}
};