前言
在上一篇文章中,我们学习了八大排序算法中的前四种排序,分别是直接插入排序,希尔排序,简单选择排序,堆排序。
接下俩,我们将继续学习剩下的四种排序算法,分别是冒泡排序,快速排序,归并排序,基数排序。
冒泡排序
冒泡排序思路比较简单:
- 将序列当中的左右元素,依次比较,保证右边的元素始终大于左边的元素;
( 第一轮结束后,序列最后一个元素一定是当前序列的最大值;) - 对序列当中剩下的n-1个元素再次执行步骤1。
- 对于长度为n的序列,一共需要执行n-1轮比较
(利用while循环可以减少执行次数)
代码实现:
python版本:
def bubble_sort(List):
for index in range(0,len(List)-1):
for each in range(0,len(List)-1-index):
if List[each]>List[each+1]:
temp = List[each+1]
List[each+1] = List[each]
List[each] = temp
return List
C++版本:
void swap(int &a, int &b) {
int temp = a;
a = b;
b = temp;
}
void bubble_sort(int array[],int n) {
if(n>=1) {
for (int j = 0; j < n-1; j++) {
if (array[j] > array[j + 1])
swap(array[j], array[j + 1]);
}
bubble_sort(array, n - 1);
}
}
归并排序
归并排序的算法思想其实就是分治,对于一个无序的数组,他的排序任务可以按照如下步骤完成:
1 把前一半数组排序
2 把后一半数组排序
3 把两半归并形成一个新的有序数组,然后再拷贝回原数组,归并完成。
代码实现:
python版本:
def mergearray(L,first,mid,last,temp):
#对i,j,k分别进行赋值
i,j,k = first,mid+1,0
#当左右两边都有数时进行比较,取较小的数
while (i <= mid) and (j <= last):
if L[i] <= L[j]:
temp[k] = L[i]
i = i+1
k = k+1
else:
temp[k] = L[j]
j = j+1
k = k+1
#如果左边序列还有数
while (i <= mid):
temp[k] = L[i]
i = i+1
k = k+1
#如果右边序列还有数
while (j <= last):
temp[k] = L[j]
j = j+1
k = k+1
#将temp当中该段有序元素赋值给L待排序列使之部分有序
for x in range(0,k):
L[first+x] = temp[x]
def merge_sort(L,first,last,temp):
if first < last:
mid = (int)((first + last) / 2)
merge_sort(L,first,mid,temp)
merge_sort(L,mid+1,last,temp)
mergearray(L,first,mid,last,temp)
def merge_sort_array(L):
temp = len(L)*[None]
merge_sort(L,0,len(L)-1,temp)
if __name__ == "__main__":
array = [16, 7, 3, 20, 17, 8]
#print(array)
merge_sort_array(array)
print("排序最终结果:", array)
C++版本:
void merge(int a[], int s,int m,int e,int tmp[]) {
/*将数组a的局部a[s,m]和a[m+1,e]合并到tmp中,然后再拷贝回a数组*/
int pb = 0;
int p1 = s, p2 = m + 1;
while (p1 <= m && p2 <= e) {
if (a[p1] <= a[p2]) {
tmp[pb++] = a[p1++];
}
else {
tmp[pb++] = a[p2++];
}
}
while (p1 <= m)
tmp[pb++] = a[p1++];
while (p2 <= e)
tmp[pb++] = a[p2++];
for (int i = 0; i < e - s + 1; i++)
a[s + i] = tmp[i];
}
void merge_sort(int array[],int s,int e, int tmp[]) {
if (s < e){
int m = s + (e - s) / 2;
merge_sort(array, s, m, tmp);
merge_sort(array, m + 1, e, tmp);
merge(array, s, m, e, tmp);
}
}
快速排序
分治的又一个典型应用:快速排序
一个无序数组的排序任务可以看作是以下步骤完成的:
1 假设k=a[0],将k挪到适当位置,使得比k小的元素都在k左边,比k大的元素都在k右边,和k相等的,无所谓左右
2 把k左边的部分快速排序
3 把k右边的部分快速排序
python版本:
def quick_sort(L,start,end):
if start < end:
i , j , pivot = start , end , L[start]
while i < j:
#从右开始向左寻找第一个小于pivot的值
while (i < j) and (L[j] >= pivot):
j = j-1
#将小于pivot的值移到左边
if (i < j):
L[i] = L[j]
i = i+1
#从左开始向右寻找第一个大于pivot的值
while (i < j) and (L[i] < pivot):
i = i+1
#将大于pivot的值移到右边
if (i < j):
L[j] = L[i]
j = j-1
L[i] = pivot
#左侧序列继续排序
quick_sort(L,start,i-1)
#右侧序列继续排序
quick_sort(L,i+1,end)
C++版本:
void swap(int &a, int &b) {
int temp = a;
a = b;
b = temp;
}
void quick_sort(int a[], int s, int e) {
if (s >= e)
return;
int k = a[s];
int i = s, j = e;
while (i != j) {
while (j > i && a[j] >= k)
--j;
if (i < j) {
swap(a[i], a[j]);
i = i + 1;
}
while (i < j && a[i] <= k)
++i;
if (i < j) {
swap(a[i], a[j]);
j =j - 1;
}
}
quick_sort(a, s, i - 1);
quick_sort(a, i + 1, e);
}
基数排序
通过基数排序对数组{53, 3, 542, 748, 14, 214, 154, 63, 616},它的示意图如下:
在上图中,首先将所有待比较树脂统一为统一位数长度,接着从最低位开始,依次进行排序。
1. 按照个位数进行排序。
2. 按照十位数进行排序。
3. 按照百位数进行排序。
排序后,数列就变成了一个有序序列。
代码实现:
python版本 :
def get_max(L):
maxNum = L[0];
for each in range(1,len(L)):
if each>maxNum:
maxNum = each;
return maxNum
def count_sort(L,exp):
output = len(L)*[None]
buckets = 10*[0]
#将数据出现的次数存储在buckets[]中
for each in range(0,len(L)):
buckets[( L[each] // exp) % 10] = buckets[(L[each] // exp) % 10] + 1
#更改buckets[i]。目的是让更改后的buckets[i]的值,关联该数据在output[]中的位置。
for each in range(1,10):
buckets[each] = buckets[each]+buckets[each-1]
#将数据存储到临时数组output[]中
for each in range(len(L)-1,-1,-1):
output[ buckets[ (L[each] // exp)%10] - 1] = L[each]
buckets[( L[each] // exp) % 10] = buckets[( L[each] // exp) % 10] - 1
#将排序好的数据赋值给L
for each in range(0,len(L)):
L[each] = output[each]
def radix_sort(L):
#获得数组中最大的数
maxNum = get_max(L)
#指数,exp=1对个位排序,exp=10对十位排序,...
exp=1
while maxNum//exp>0:
count_sort(L,exp);
exp = exp*10
if __name__ == "__main__":
array = [16, 7, 3, 20, 17, 8,33]
#print(array)
radix_sort(array)
print("排序最终结果:", array)
C++版本:
int get_max(int a[], int n)
{
int i, max;
max = a[0];
for (i = 1; i < n; i++)
if (a[i] > max)
max = a[i];
return max;
}
void count_sort(int a[], int n, int exp)
{
int output[n]; // 存储"被排序数据"的临时数组
int i, buckets[10] = {0};
// 将数据出现的次数存储在buckets[]中
for (i = 0; i < n; i++)
buckets[ (a[i]/exp)%10 ]++;
// 更改buckets[i]。目的是让更改后的buckets[i]的值,关联该数据在output[]中的位置。
for (i = 1; i < 10; i++)
buckets[i] += buckets[i - 1];
// 将数据存储到临时数组output[]中
for (i = n - 1; i >= 0; i--)
{
output[buckets[ (a[i]/exp)%10 ] - 1] = a[i];
buckets[ (a[i]/exp)%10 ]--;
}
// 将排序好的数据赋值给a[]
for (i = 0; i < n; i++)
a[i] = output[i];
}
void radix_sort(int a[], int n)
{
int exp; // 指数。当对数组按各位进行排序时,exp=1;按十位进行排序时,exp=10;...
int max = get_max(a, n); // 数组a中的最大值
// 从个位开始,对数组a按"指数"进行排序
for (exp = 1; max/exp > 0; exp *= 10)
count_sort(a, n, exp);
}
小结:
至此,排序算法差不多结束了,接下来继续学习数据结构中的三大查找算法。
ps:参考博客
https://www.cnblogs.com/skywang12345/p/3603669.html