1 冒泡排序
算法原理:
-
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
-
对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
-
针对所有的元素重复以上的步骤,除了最后一个。
-
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
时间/空间复杂度:
若文件的初始状态是正序的,一趟扫描即可完成排序。所需的关键字比较次数 和记录移动次数 均达到最小值:
, 。
所以,冒泡排序最好的时间复杂度为 。
若初始文件是反序的,需要进行 趟排序。每趟排序要进行 次关键字的比较(1≤i≤n-1),且每次比较都必须移动记录三次来达到交换记录位置。在这种情况下,比较和移动次数均达到最大值:
冒泡排序的最坏时间复杂度为 。
综上,因此冒泡排序总的平均时间复杂度为 ,冒泡排序的空间复杂度为O(1)。
代码实现:
void swap(int &num1, int &num2){
int tmp = num1;
num1 = num2;
num2 = tmp;
}
//冒泡排序:升序
void BubbleSort(std::vector<int> &nums){
int size = nums.size();
if (size < 2)
return;
int i, j;
for (i = 0; i < size; ++i)
for (j = 1; j < size - i; ++j){
if (nums[j] < nums[j-1])
swap(nums[j], nums[j-1]);
}
}
2 插入排序(直接插入)
算法原理:
⒈ 从第一个元素开始,该元素可以认为已经被排序。
⒉ 取出下一个元素,在已经排序的元素序列中从后向前扫描。
⒊ 如果该元素(已排序)大于新元素,将该元素移到下一位置。
⒋ 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置。
⒌ 将新元素插入到下一位置中。
⒍ 重复步骤2~5。
时间/空间复杂度:
时间复杂度最好为,最差为 ,冒泡排序的空间复杂度为O(1)。
代码实现:
void swap(int &num1, int &num2){
int tmp = num1;
num1 = num2;
num2 = tmp;
}
//插入排序:升序
void InsertSort(std::vector<int> &nums){
int size = nums.size();
if (size < 2)
return;
int i, j;
for (i = size - 1; i > 0; --i)
for (j = size - i; j > 0; --j){
if (nums[j] < nums[j - 1])
swap(nums[j], nums[j - 1]);
}
}
3 选择排序(直接选择)
算法原理:
每一趟从待排序的记录中选出最小的元素,顺序放在已排好序的序列最后,直到全部记录排序完毕。也就是:每一趟在n-i+1(i=1,2,…n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录。
时间/空间复杂度:
时间复杂度最好为,最差为 ,冒泡排序的空间复杂度为O(1)。
代码实现:
void swap(int &num1, int &num2){
int tmp = num1;
num1 = num2;
num2 = tmp;
}
//选择排序:升序
void SelectSort(std::vector<int> &nums){
int size = nums.size();
if (size < 2)
return;
int i, j;
int minNum = 0;
int minIndex = 0;
for (i = 0; i < size; ++i){
minNum = nums[i];
minIndex = i;
for (j = i + 1; j < size; ++j){
if (nums[j] < minNum){
minNum = nums[j];
minIndex = j;
}
}
swap(nums[i], nums[minIndex]);
}
}
4 归并排序
算法原理:
归并排序可以看这个博客讲的不错:https://www.cnblogs.com/skywang12345/p/3602369.html
时间/空间复杂度:
时间复杂度最好为O(nlogn),最坏为O(nlogn),空间复杂度为O(n)。
代码实现:
//归并排序-升序
void MergeSort(std::vector<int> &nums, int left, int right){
if (left == right)
return;
int mid = (left + right) / 2;
if (left < right){
MergeSort(nums, left, mid);
MergeSort(nums, mid + 1, right);
Merge(nums, left, mid, right);
}
}
void Merge(std::vector<int> &nums, int left, int mid, int right){
int i = left;//左序列指针
int j = mid + 1;//右序列指针
int size = right - left + 1;
std::vector<int> tmp(size);
int cnt = 0;
while (i <= mid && j <= right){
nums[i] <= nums[j] ? tmp[cnt++] = nums[i++] : tmp[cnt++] = nums[j++];
}
while (i <= mid) {//将左边剩余元素填充进temp中
tmp[cnt++] = nums[i++];
}
while (j <= right){//将右序列剩余元素填充进temp中
tmp[cnt++] = nums[j++];
}
cnt = 0;
//将temp中的元素全部拷贝到原数组中
while (left <= right){
nums[left++] = tmp[cnt++];
}
}
额外知识点:(1)小和问题
(2)逆序对问题