数据结构与算法——排序算法(二)
1、归并排序
1.1 基本思想
归并排序是利用分治的策略,将原始的数组分解成小的数组然后进行递归排序的过程。该策略主要包括两个部分,第一个部分是分 , 第二个部分是治。分就是将原始的数组分解成若干个小的数组,治就是将小的的数组合并成有序的过程。类似于下图所示:
根据上图所示,我首先经历的是一个分的过程,我们数据分解成单个元素构成的数组的时候,此时数组中的元素就是数组的排序。下一步就就是合并的过程,根据两个数组中元素的大小,将两个元素中的数据合并成一个有序的数组。
在归并排序中最重要的就是合并的过程,我们采用两张图来解释以下:
1.2 代码实现
void merge(vector<int> &v, int left, int midd, int right, vector<int> & temp)
{
int i = left; //左侧有序序列的初始索引
int j = midd + 1;//j表示右侧有序序列的初始索引
//先把左右两边的数据按照规则拷贝到temp中去,一直到左右两边有一方处理完成
while (i <= midd && j <= right)
{
if (v[i] < v[j])
temp.push_back(v[i++]);
else
temp.push_back(v[j++]);
}
//如果另外一侧存在剩余,则将剩余的部分拷贝到temp中去
while (i <= midd)
temp.push_back(v[i++]);
while (j <= right)
temp.push_back(v[j++]);
//将temp中的数据在拷贝回v中去
int templeft = left;
while (templeft <= right)
{
v[templeft++] = *temp.begin();
temp.erase(temp.begin());
}
}
void mergeSort(vector<int> &v,int left,int right,vector<int> &temp)
{
if (left < right)
{
int mid = (left + right) / 2;
mergeSort(v, left, mid, temp);
mergeSort(v, mid + 1, right, temp);
merge(v, left, mid, right, temp);
}
}
1.3 时间复杂度分析
归并排序的时间复杂度可以分为两块,第一个部分是分 O ( l o g n ) O(log_n) O(logn),第二个部分是合并 O ( n ) O(n) O(n),所以总的时间复杂度为 O ( n l o g n ) O(nlog_n) O(nlogn)。
2 基数排序
2.1 基本思想
它通过键值上的各个位的值,将要排序的数据分配到各个桶中去,达到排序的作用。基数排序通过将所有待比较的数值统一成同样数位的长度,数位比较短的前面补零(比如 100,010,004)。然后从最低位开始,依次进行一次排序,这样从最低位排序,一直到最高位排序结束,整个数列就变成了一个有序的数列。
如下面的图所示:假设待排序的数列为[53,3,542,748,14,214]
2.2 代码实现
void radixSort(vector<int> &v)
{
vector<vector<int>> bucket;
bucket.resize(10);
int max_value = v[0];
for (int i = 1; i < v.size(); i++)
{
if (v[i] > max_value)
max_value = v[i];
}
int count = 0;
while (max_value > 0)
{
max_value /= 10;
count += 1;
}
int index = 0;
//针对各个位置的元素进行排序,个位,十位,百位。。。
for (int m = 0, n = 1; m < count; m++, n *= 10)
{
for (int j = 0; j < v.size(); j++)
{
int digit = (v[j] / n) % 10;
bucket[digit].push_back(v[j]);
}
index = 0;
for (int i = 0; i < bucket.size(); i++)
{
while(bucket[i].size() != 0)
{
v[index] = *bucket[i].begin();
bucket[i].erase(bucket[i].begin());
index++;
}
}
}
}
注意:上述的代码的数组中不能存在负数。
2.3 复杂度分析
基数排序是典型的空间换实时间的排序方式,其时间复杂度为 O ( n ∗ k ) O(n*k) O(n∗k),k表示最大数据的位数。