数据结构——八大排序算法(2)

 前言

在上一篇文章中,我们学习了八大排序算法中的前四种排序,分别是直接插入排序,希尔排序,简单选择排序,堆排序。

接下俩,我们将继续学习剩下的四种排序算法,分别是冒泡排序,快速排序,归并排序,基数排序。

冒泡排序

冒泡排序思路比较简单:

  1. 将序列当中的左右元素,依次比较,保证右边的元素始终大于左边的元素;
    ( 第一轮结束后,序列最后一个元素一定是当前序列的最大值;)
  2. 对序列当中剩下的n-1个元素再次执行步骤1。
  3. 对于长度为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 把两半归并形成一个新的有序数组,然后再拷贝回原数组,归并完成。

扫描二维码关注公众号,回复: 5949587 查看本文章

代码实现:

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

https://www.cnblogs.com/hokky/p/8529042.html

https://www.cnblogs.com/dwj411024/p/5978821.html

猜你喜欢

转载自blog.csdn.net/cv_pyer/article/details/89393211