一、冒泡排序
上浮法 :从数组末尾开始,连续比较相邻两个元素,使其符合排序。比较一个循环后,处于数组前排的元素最先符合(最大 or 最小),不再参与下一个循环的比较。
下沉法:从数组开头开始,连续比较相邻两个元素,使其符合排序。比较一个循环后,处于数组后排的元素最先符合(最大 or 最小),不再参与下一个循环的比较。
冒泡法最优时间复杂度可以达到O(n),最差可以达到O(n^2)
【注】如果上一次循环已经符合排序,即没有交换过一次,则已经排序完成,得到结果,不需要再进行下一次循环
参考代码 C++实现
//冒泡排序-上浮 从小到大排序
void bubbleSort(vector<int>& nums)
{
//i记录参与比较的起始位置
for (int i = 0; i < nums.size(); ++i)
{
bool isSwap = false;//如果isSwap为true,则循环有交换操作
for (int j = nums.size()-1; j > i; --j)
{
//逆序则交换
if (nums[j] < nums[j - 1]) {
swap(nums[j], nums[j - 1]);
isSwap = true;
}
}
//此轮循环已经有序,不需要再遍历
if (isSwap == false) {
break;
}
}
}
二、选择排序
个人理解选择排序可以概括为:为指定位置选择合适的值
以从小到大排序为例,具体做法是:以位置作为第一重循环,为第0的位置选入最小的值......以此类推
参考代码 C++实现
//选择排序 从小到大排序
void selectionSort(vector<int>& nums)
{
//i记录参与比较的起始位置
//为位置i寻找合适的值
for (int i = 0; i < nums.size(); ++i)
{
int minIdx = i; //保存目前循环中最小的位置
for (int j = i; j < nums.size(); ++j)
{
minIdx = nums[minIdx] > nums[j] ? j : minIdx;
}
if (minIdx != i)
{
swap(nums[minIdx], nums[i]);
}
}
}
三、插入排序
个人理解插入排序可以概括为:把指定的值插入到合适的位置
以从小到大排序为例,具体做法是:从0位置开始遍历数组每个值,设其前面是有序的,将其插入到有序序列中合适位置
参考代码 C++实现
//插入排序 从小到大排序
void insertionSort(vector<int>& nums)
{
for (int i = 1; i < nums.size(); ++i)
{
int temp = nums[i]; //将temp值插入合适位置
int j = i;
//向有序序列查找temp的位置
while (j > 0 && temp < nums[j-1])
{
nums[j] = nums[j - 1];
--j;
}
nums[j] = temp;
}
}
四、归并算法
该算法采用分治法思想。把序列分解成若干子序列,使各子序列有序,并且将子序列有序合并得到最终有序序列。
递归法:自上而下解决问题。从逻辑上讲,递归法是先尝试排序数组,在排序中分解成了子数组进行排序。是1、8分成4,4;2、4分成2,2的过程
迭代法:自下而上解决问题。从逻辑上讲,迭代法是先排序最小子数组,然后合并排序大数组。是1、2,2合为4;4, 4合为8的过程
代码实现 C++ ——递归
vector<int> mergeSort(vector<int>& nums1, vector<int>& nums2)
{
vector<int> mergeNums;
//itn1 = nums1迭代器 itn2 = nums2迭代器
auto itn1 = nums1.begin();
auto itn2 = nums2.begin();
while (nums1.end() != itn1 || nums2.end() != itn2 )
{
//如果nums1已经全部遍历,剩下的nums2全部push进结果数组中
if (nums1.end() == itn1)
{
while (nums2.end() != itn2)
{
mergeNums.push_back(*itn2++);
}
break;
}
//如果nums2已经全部遍历,剩下的nums1全部push进结果数组中
else if (nums2.end() == itn2)
{
while (nums1.end() != itn1)
{
mergeNums.push_back(*itn1++);
}
break;
}
//比较nums1