排序算法专题(C与python实现):冒泡/选择/插入/希尔/归并/快速

1.冒泡排序:

  • 将序列当中的相邻的两个元素,从左至右,依次比较,通过交换,两个元素,大的放在前面(左边),小的放在后面(右边),第一轮结束之后,序列的最后一个元素一定是当前序列中最大值
  • 对序列中剩下的n-1个元素在执行步骤1
  • 对于长度为n的序列,每个元素都需要一轮从左到右的两两比较,除了最后一个元素,也就是一共需要n-1轮(0到n-2)比较。
  • 第1轮比较,有n个元素进行两两比较需要n-1次第2轮比较,有n-1个元素进行两两比较需要n-2次第i轮比较,有n-(i-1)个元素进行两两比较需要n-i次(这里的i从1开始,如果从零开始,需要n-i-1次)
  • 两层循环:第一层,轮数;第二层,每一轮剩余元素两两比较

在这里插入图片描述
C语言

#include <stdio.h>
void bubble_sort(int arr[], int n) {
    int i, j, temp;
    for (i = 0; i < n - 1; i++)     //需要n-1轮(0到n-2)比较
        for (j = 0; j < n - 1 - i; j++)     //第i轮有n-(i-1)个元素,需要n-i次(这里的i是从1开始)比较,需要n-i-1次(这里的i从0开始)
            if (arr[j] > arr[j + 1]) {
                temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
}
int main() {
    int arr[] = { 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70 };
    int n = (int) sizeof(arr) / sizeof(*arr);//数组所占字节数/数组第一个元素所占字节,等于数组元素个数
    bubble_sort(arr, n);
    int i;
    for (i = 0; i < len; i++)   //从左到右,从小到大,依次输出
        printf("%d ", arr[i]);
    return 0;
}

Python语言

def bubble_sort(L):
    length = len(L)  #序列长度为length,
    for x in range(1,length):#需要执行length-1轮交换(1到length-1)
        for i in range(0,length-x):#第x轮比较有length-x个元素,需要length-x次比较(如果x从0开始,需要length-x-1次)
            if L[i] > L[i+1]:
                temp = L[i]
                L[i] = L[i+1]
                L[i+1] = temp

C++语言

template

//




2.选择排序:

  • 从未排序序列中,找到最小的元素,放在起始位置
  • 如果最小元素不是未排序序列的第一个元素,将其和第一个元素互换;
  • 从剩余的未排序序列中的n-1个元素,找到最小的元素,重复步骤1和2
  • 第一轮,从n个元素中找到的最小值放在第一个元素位置(假设第一个元素为最小值,依次与剩余元素比较和交换),第二轮,从n-1个元素中找到的最小值放在第二个元素位置(假设第二个元素为最小值,依次与剩余元素比较和交换),依次类推。
  • 两层循环:第一层,遍历每个元素,轮数;第二层,当前遍历元素(假设的最小值)与余下元素进行比较和交换

在这里插入图片描述

void swap(int *a,int *b) //交换两个变量
{
    int temp = *a;
    *a = *b;
    *b = temp;
}
void selection_sort(int arr[], int n) 
{
    int i,j;
 
    for (i = 0 ; i < n - 1 ; i++) //遍历每个元素,每个元素作为每轮假设的最小值,轮数n-1
    {
        int min = i;
        for (j = i + 1; j < n; j++)     //假设的最小值作为该轮中的第一个元素与剩余未排序的元素进行比较和交换,j表示剩余元素下表
            if (arr[j] < arr[min])    //找到目前最小值
                min = j;    //记录最小值,始终将最小值记录在下表min的元素中
           swap(&arr[min], &arr[i]);    //该轮中最小值与假设的最小值之间进行位置交換
    }
}

Python语言

def select_sort(L):
    for x in range(0,len(L)):#依次遍历序列中的每一个元素,作为每轮中的假设的最小值,轮数n-1
        minimum = L[x]   #当前遍历元素作为该轮中假设的最小值
        for i in range(x+1,len(L)):#当前遍历元素(作为第一个元素)与剩下的元素依次比较寻找最小元素,i(x+1)为剩余元素下标
            if L[i] < minimum:
                temp = L[i];
                L[i] = minimum;
                minimum = temp
#将比较过程中的最小值与假设的最小值进行交换
        L[x] = minimum    #将该轮中的最小值与假设的最小值进行交换

3.插入排序

  • 第一个元素默认为已经被排序,从第二个元素开始,将数组中所有的元素依次从后向前(从右向左)与已排序元素逐个比较大小
  • 如果该元素小于已排序元素,则交换两者位置,即已排序元素向后移,该元素插进来,直到找到已排序元素小于或等于该元素的位置
  • 重复步骤2
  • 两层循环:第一层,遍历所有数组元素,轮数;第二层,该轮元素与已排序元素进行比较,如果小于已排序元素,则交换两者

在这里插入图片描述
C语言

void insertion_sort(int arr[], int n)
{
    int i,j,temp;
    for (i=1;i<n;i++)   //n-1轮
    {
            temp = arr[i];//该轮元素
            for (j=i;j>0 && arr[j-1]>temp;j--)  //已排序元素(该轮元素前面的元素)大于该轮元素,则交换
                    arr[j] = arr[j-1];
            arr[j] = temp;
    }
}

Python语言

def insert_sort(L):
    for x in range(1,len(L)):#遍历数组中的所有元素,其中0号索引元素默认已排序,因此从1开始
        for i in range(x-1,-1,-1): #将该元素与已排序好的前序数组依次比较,如果该元素小,则交换,range(x-1,-1,-1):从x-1倒序循环到0
            if L[i] > L[i+1]:   #判断:如果符合条件则交换
                temp = L[i+1]
                L[i+1] = L[i]
                L[i] = temp

4.希尔排序(shell sort)

  • 插入排序的改进版,缩小增量排序,通过选择希尔增量gap的方式将整个待排序序列分割成若干子序列,分别进行插入排序
  • 每次将gap折半,循环步骤1,当gap为1时,排序完成
  • 三层循环:第一层,gap依次折半,对整个序列分组,直到gap=1;第二层和第三层是插入排序的两层循环
    在这里插入图片描述
    在这里插入图片描述
    C语言
void shell_sort(int arr[], int n) {
    int gap, i, j;
    int temp;
    for (gap = n >> 1; gap > 0; gap = gap >> 1)  //右移一位,折半
        for (i = gap; i < n; i++) {       //插入排序算法
            temp = arr[i];
            for (j = i - gap; j >= 0 && arr[j] > temp; j -= gap)
                arr[j + gap] = arr[j];
            arr[j + gap] = temp;
        }
}

Python语言

def insert_shell(L):
    gap = (int)(len(L)/2)  #初始化gap值,此处利用序列长度的一般为其赋值
    while (gap >= 1):      #第一层循环:依次改变gap值对列表进行分组
        for x in range(gap,len(L)): #range(x-gap,-1,-gap):从x-gap开始与选定元素开始倒序比较,每个比较元素之间间隔gap,range(gap,len(L)):从gap开始
            for i in range(x-gap,-1,-gap):
                if L[i] > L[i+gap]:   #如果该组当中两个元素满足交换条件,则进行交换  
                    temp = L[i+gap]
                    L[i+gap] = L[i]
                    L[i] =temp
        gap = (int)(gap/2)    #while循环条件折半

5.归并排序(merge sort)

  • 采用分治法的典型算法,将整个序列折半拆分成子序列,对子序列分别采用归并排序
  • 最后将两个排好序的子序列合并成一个序列
  • L[first…mid]为第一段,L[mid+1…last]为第二段,并且两端已经有序,现在要将两端合成L[first…last]并且也有序
  • 首先依次从第一段与第二段中取出元素比较,将较小的元素赋值给temp[]
  • 重复执行上一步,当某一段赋值结束,则将另一段剩下的元素赋值给temp[],此时将temp[]中的元素复制给L[],则得到的L[first…last]有序
  • 采用递归的方法,将待排序列分成A,B两组
  • 重复对A、B序列分组,直到分组后组内只有一个元素,此时组内所有元素有序,则分组结束

python语言

def mergearray(L,first,mid,last,temp):#合并序列L[first...mid]与L[mid+1...last]的函数
    i,j,k = first,mid+1,0     #对i,j,k分别进行赋值
    while (i <= mid) and (j <= last):   #当左右两边都有数时进行比较,取较小的数
        if L[i] <= L[j]:      #i是从first开始,j是从mid+1开始,k从0开始
            temp[k] = L[i]    #将小值赋给temp,继续取值与该大值比较
            i = i+1
            k = k+1
        else:
            temp[k] = L[j]    #将小值赋给temp,继续取值与该大值比较
            j = j+1
            k = k+1
   
    while (i <= mid):    #如果左边序列还有数,将数全部赋给temp
        temp[k] = L[i]
        i = i+1
        k = k+1
   
    while (j <= last):    #如果右边序列还有数,将数全部赋给temp
        temp[k] = L[j]
        j = j+1
        k = k+1
    for x in range(0,k):     #将temp当中该段有序元素赋值给L待排序列使之部分有序
        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]    #声明一个长度为len(L)的空列表 
    merge_sort(L,0,len(L)-1,temp)    #调用归并排序

C语言

void merge_sort_recursive(int arr[], int reg[], int start, int end) {   //递归法
    if (start >= end)
        return;
    int len = end - start, mid = (len >> 1) + start;
    int start1 = start, end1 = mid;
    int start2 = mid + 1, end2 = end;
    merge_sort_recursive(arr, reg, start1, end1);
    merge_sort_recursive(arr, reg, start2, end2);
    int k = start;
    while (start1 <= end1 && start2 <= end2)
        reg[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++];
    while (start1 <= end1)
        reg[k++] = arr[start1++];
    while (start2 <= end2)
        reg[k++] = arr[start2++];
    for (k = start; k <= end; k++)
        arr[k] = reg[k];
}
void merge_sort(int arr[], const int len) {
    int reg[len];
    merge_sort_recursive(arr, reg, 0, len - 1);
}

6.快速排序(Quick Sort)

  • 在序列中选择一个基准数,遍历序列中的所有数,比基准数大的数放在右侧,比基准数小的放在左侧
  • 左侧和右侧成为子序列,对子序列分别重复步骤1,进行递归式重复,直到子序列只有一个数为止。

Python语言

#L:待排序的序列;start排序的开始index,end序列末尾的index
#对于长度为length的序列:start = 0;end = length-1
def quick_sort(L,start,end):
    if start < end:
        i , j , pivot = start , end , L[start]  #pivot的值为第一个元素作为基准值
        while i < j:
#从右开始向左寻找第一个小于pivot的值
            while (i < j) and (L[j] >= pivot):  #左侧为小值,所以从右向左找小值
                j = j-1      #相对于j--,如果大于基准值,换一个数进行比较

            
            if (i < j):       #将小于pivot的值移到左边,i从0开始
                L[i] = L[j]
                i = i+1       #i++
#从左开始向右寻找第一个大于pivot的值
            while (i < j) and (L[i] < pivot):  #遍历循环查找,小于基准值一直循环,大于就脱离循环,进入if判断
                i = i+1


            if (i < j):     #将大于pivot的值移到右边,j从end开始
                L[j] = L[i]
                j = j-1
#循环结束后,说明 i=j(i++和j--分别从0和end遍历到了基准数下标),此时左边的值全都小于pivot,右边的值全都大于pivot
#pivot的位置移动正确,那么此时只需对左右两侧的序列调用此函数进一步排序即可
#递归调用函数:依次对左侧序列:从0 ~ i-1//右侧序列:从i+1 ~ end
        L[i] = pivot   #此时自然就有基准数等于序列中下标为i的元素

#左侧序列继续排序
        quick_sort(L,start,i-1)
#右侧序列继续排序
        quick_sort(L,i+1,end)

C语言

void swap(int *x, int *y) {
    int t = *x;
    *x = *y;
    *y = t;
}
void quick_sort_recursive(int arr[], int start, int end) {
    if (start >= end)
        return;
    int mid = arr[end];
    int left = start, right = end - 1;
    while (left < right) {
        while (arr[left] < mid && left < right)
            left++;
        while (arr[right] >= mid && left < right)
            right--;
        swap(&arr[left], &arr[right]);
    }
    if (arr[left] >= arr[end])
        swap(&arr[left], &arr[end]);
    else
        left++;
    if (left)
        quick_sort_recursive(arr, start, left - 1);
    quick_sort_recursive(arr, left + 1, end);
}
void quick_sort(int arr[], int len) {
    quick_sort_recursive(arr, 0, len - 1);
}

7.堆排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值