常见的排序实现

前言:记录常见的排序方法

插入排序

直接插入排序

1、数据分为两部分,一开始有序部分包含1个元素

2、依次将无序部分的元素插入到有序部分当中

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main()
{
    int a[] = {99999,1,99,22,66,7,2,3,11}; // a[0]作为哨兵
    int arrayLength = sizeof(a)/sizeof(int);
    int temp;
    for(int i=2;i<=arrayLength;i++)
    {
        if(a[i]>a[i-1])
            continue;
        a[0] = a[i]; // 哨兵存储当前要进行比较的值
        temp = a[i];
        a[i] = a[i-1];
        a[i-1] = temp;
        for(int j=i-2;j>=1;j--)
        {
            if(temp < a[j])
            {
                a[j+1] = a[j];
                a[j] = temp;
            }
        }   
    }
    a[0] = 99999;
    // printf
    for(int i=0;i<arrayLength;i++)
        a[i] != 99999 && printf("%d ", a[i]);
    return 0;
}

交换排序

冒泡排序

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main(){
    int arr[] = {1,5,2,7,8,4,6,9,0,3};
    int temp;
    int arrLength = sizeof(arr)/sizeof(int); 
    for (int i=0;i<arrLength-1;i++){
        for(int j=0;j<arrLength-i-1;j++)
            if(arr[j] > arr[j+1])
            {temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;}
    }
    for (int i = 0; i < arrLength; i++)
        printf("%d\n", arr[i]);
    return 0;

快速排序

快速排序是对冒泡排序的一种改进,是非常重要且应用比较广泛的一种高效率排序算法。

快速排序是通过多次比较和交换来实现排序,在一趟排序中把将要排序的数据分成两个独立的部分,对这两部分进行排序使得其中一部分所有数据比另一部分都要小,然后继续递归排序这两部分,最终实现所有数据有序。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void quick_sort(int* arr, int left, int right)
{
    int temp = arr[0];
    int left_temp = left,right_temp=right;
    if(left+1>=right)return;
    while(left_temp<right_temp)
    {
        while(1)
        {
            if(temp>arr[right_temp])
            {
                arr[left_temp] = arr[right_temp];
                left_temp++;
                break;
            }
            right_temp--;
            if(left_temp>=right_temp)break;
        }
        if(left_temp>=right_temp)break;
        while(1)
        {
            if(temp<arr[left_temp])
            {
                arr[right_temp] = arr[left_temp];
                right_temp--;
                break;
            }
            left_temp++;
            if(left_temp>=right_temp)break;
        }
    }
    arr[left_temp]=temp;
    quick_sort(arr, left, left_temp-1);
    quick_sort(arr, left_temp+1, right);
}


int main(){
    int arr[] = {19,97,9,17,1,8};
    int arrLength = sizeof(arr)/sizeof(int); 
    quick_sort(arr, 0, arrLength-1);
    for (int i = 0; i < arrLength; i++)
        printf("%d ", arr[i]);
    return 0;
}

选择排序

简单选择排序

工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main()
{
    int a[] = {1,5,6,7,8,2,3,4};
    int arrayLength = sizeof(a)/sizeof(int);
    int temp;
    for(int i=0;i<arrayLength-1;i++)
    {
        int min = i; // 标识符可以是记录对应值下标,这里同样可以是 min = a[i]
        for(int j=i+1;j<arrayLength;j++)
        {
            if(a[min]>a[j])
            {
                temp = a[min]; // 如果上面是min=a[i],那么这里直接是tmep = min
                a[min] = a[j];
                a[j] = temp;
            }
        } 
    }
    for(int i=0;i<arrayLength;i++)
        printf("%d ", a[i]);
    return 0;
}

堆排序

X

计数排序

计数排序是一个非基于比较的排序算法,该算法于1954年由 Harold H. Seward 提出。它的优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k)(其中k是整数的范围),快于任何比较排序算法。

虽然计数排序看上去很强大,但是它存在两大局限性:

1.当数列最大最小值差距过大时,并不适用于计数排序

比如给定 20 个随机整数,范围在 0 到 1 亿之间,此时如果使用计数排序的话,就需要创建长度为 1 亿的数组,不但严重浪费了空间,而且时间复杂度也随之升高。

2.当数列元素不是整数时,并不适用于计数排序

如果数列中的元素都是小数,比如 3.1415,或是 0.00000001 这样子,则无法创建对应的统计数组,这样显然无法进行计数排序。

正是由于这两大局限性,才使得计数排序不像快速排序、归并排序那样被人们广泛适用。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void count_sort(int* arr, int length)
{
    int max=arr[0],min=arr[0];
    for(int i=1;i<length;i++)
    {
        if(max<arr[i])max=arr[i];
        if(min>arr[i])min=arr[i];
    }
    // printf("max:%d, min:%d", max,min);
    int new_size = max - min + 1;
    int* p_array = (int*)malloc(sizeof(int)*new_size);
    memset(p_array, 0, sizeof(int)*new_size);
    for(int i=0;i<length;i++)
        p_array[arr[i]-min]++;
    for(int i=0;i<new_size;i++)
        while(p_array[i]>0)
        {
            printf("%d ", i);
            p_array[i] = p_array[i]-1;
        }
    printf("\n");
}

int main(){
    int arr[18] = {1,5,2,7,8,4,6,22,9,33,0,3,11,22,33,3,22,11};
    int length = sizeof(arr)/sizeof(int); 
    count_sort(arr, length);
    return 0;
}

归并排序

归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。

简单理解的话就是将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。

比如我们准备排序的数组是:9,5,8,4,7,3,6,2

  • 第一步分组:[9584] [7362]

  • 第二步分组:[95] [84] [73] [62]

  • 第三步分组:[9] [5] [8] [4] [7] [3] [6] [2]

到这里的话已经分组完成,然后再从第三步返回排序

  • 第四步排序:[59] [48] [37] [26]

  • 第五步排序:[4589] [2367]

  • 第六步排序:[23456789]

#coding=utf-8

#拆分
def sort(arr, left, right):
	if left >= right:
		return
	mid = (left+right)//2
	sort(arr, left, mid)
	sort(arr, mid+1, right)
	merge(arr, left, mid, right)

#合并
def merge(arr, left, mid, right):
	tmp_list = []
	i,j = left, mid+1
	for k in range(right-left+1):
		if i > mid:
			tmp_list.append(arr[j])
			j += 1
		elif j > right:
			tmp_list.append(arr[i])
			i += 1
		elif arr[i]>arr[j]:
			tmp_list.append(arr[j])
			j += 1
		elif arr[i]<arr[j]:
			tmp_list.append(arr[i])
			i += 1

	# 回写到原来的arr
	for value in tmp_list:
		arr[left] = value
		left += 1

if __name__ == '__main__':
	arr = [9,5,8,4,7,3,6,2]
	sort(arr, 0, len(arr)-1)
	print(arr)
# 9,5,8,4,7,3,6,2
posted @ 2019-11-02 19:41  zpchcbd  阅读(116)  评论(0编辑  收藏  举报