针对笔试面试过程中经典的几种排序算法做个记录。
1、归并算法
基本思想
归并排序(merge sort)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各结果合在一起,即分而治之)。以下为C++实现的归并排序算法。
class Solution{
public:
vector<int> Mergesort(vector<int> num){
vector<int> result(num); // 原num直接复制一份到result数组,整个算法变成了非原址操作
int size = result.size();
mergesortcore(result, 0, size - 1);
return result;
}
void mergesortcore(vector<int> &num, int left, int right){
if (left < right){
int middle = (left + right) / 2;
mergesortcore(num, left, middle);
mergesortcore(num, middle+1, right);
merge(num, left, middle, right);
}
}
void merge(vector<int> &num, int left, int middle, int right){ //将两个有序数组合并排序
int *temp = new int[right - left + 1];
int i = left;
int j = middle + 1;
int t = 0; // 记录temp指针的索引
while (i <= middle && j <= right)
{
if (num[i] < num[j]){
temp[t++] = num[i++];
}
else{
temp[t++] = num[j++];
}
}
// 把左边剩余的数移入数组
while (i <= middle)
{
temp[t++] = num[i++];
}
// 把右边剩余的数移入数组
while (j <= right)
{
temp[t++] = num[j++];
}
for (int i = 0; i < right - left + 1; i++)
{
num[i + left] = temp[i];
}
delete[] temp;
}
};
以下为Python实现的归并排序算法。
class MergeSolution:
def MergeSort(self,arr:list) -> list:
if len(arr) <= 1:
return arr
mid = len(arr)//2
a = self.MergeSort(arr[:mid])
b = self.MergeSort(arr[mid:])
return self.Merge(a,b)
def Merge(self,a,b):
i = j = 0
res = []
while i < len(a) and j < len(b):
if a[i] <= b[j]:
res.append(a[i])
i += 1
else:
res.append(b[j])
j += 1
res.extend(a[i:])
res.extend(b[j:])
return res
归并排序算法分析
(1)稳定性
归并排序是一种稳定的排序。
(2)存储结构要求
可用顺序存储结构。也可以在链表上实现。
(3)时间复杂度
时间复杂度无论是在最好情况下还是在最坏情况下均是O(nlgn)。
(4)空间复杂度
需要一个辅助向量来暂存两有序子文件归并的结果,故其空间复杂度为O(n)
2、快速排序
基本思想:
1.先从向量中取出一个数作为轴点。
2.分区过程,将比这个轴点大的数全放到它的右边,小于或等于它的数全放到它的左边。
3.再对左右区间重复第二步,直到各区间只有一个数。
以下为C++实现的快速排序算法。
class Solution{
public:
void Quicksort(vector<int> &numbers, int low, int high){
int pivotpos;
if (low < high){
pivotpos = partition(numbers, low, high);
Quicksort(numbers, low, pivotpos - 1);
Quicksort(numbers, pivotpos + 1, high);
}
}
int partition(vector<int> &numbers, int low, int high){
int left = low, right = high;
int pivot = numbers[left]; //这里选择了最左边的为pivot(轴点)
while (left<right)
{
//顺序很重要,假如上面选择了最左边的为pivot,一定要先从右边开始找
while (pivot <= numbers[right] && left<right) //从右到左找到一个小于pivot的数
right--;
while (pivot >= numbers[left] && left<right) //从左到右找到一个大于pivot的数
left++;
swap(numbers[left], numbers[right]);
}
if (left == right)
swap(numbers[left], numbers[low]);
return left;
}
};
以下为Python实现的快速排序算法。
class Solution:
def Quicksort(self,arr:list,left:int,right:int):
if left < right:
privot_index = self.partition(arr,left,right)
self.quicksort2_1(arr,left,privot_index-1)
self.quicksort2_1(arr,privot_index+1,right)
def partition(self,arr:list,left:int,right:int) -> int:
privot = arr[left]
head = left
while left < right:
while left < right and arr[right] > privot:
right -= 1
while left < right and arr[left] <= privot:
left += 1
arr[left],arr[right] = arr[right],arr[left]
arr[head],arr[right] = arr[right],arr[head]
return right
下面是利用Python语言强大的特性实现的简洁版快速排序算法。
class Solution:
def quicksort(self,nums:list) -> list:
if len(nums) <= 1:
return nums
greater = [x for x in nums[1:] if x > nums[0]]
lesser = [x for x in nums[1:] if x <= nums[0]]
return self.quicksort(lesser)+[nums[0]]+self.quicksort(greater)
快速排序算法分析
(1)稳定性
快速排序是一种不稳定的排序。
(2)存储结构要求
可用顺序存储结构。也可以在链表上实现。
(3)时间复杂度
时间复杂度在最好情况下为O(n),平均情况是O(nlogn),最坏情况下是O(n^2)。
(4)空间复杂度
快排实现了原址操作,故其空间复杂度为O(1)
最后放一张对常见排序算法的分析图。
- 均按从小到大排列
- k:代表数值中的 “数位” 个数
- n:代表数据规模
- m:代表数据的最大值减最小值
参考:
https://blog.youkuaiyun.com/qq_25827845/article/details/70994874
https://blog.youkuaiyun.com/doubleguy/article/details/81390951
https://wiki.jikexueyuan.com/project/easy-learn-algorithm/fast-sort.html
https://blog.youkuaiyun.com/MoreWindows/article/details/6684558
https://github.com/huihut/interview