常见的排序实现
前言:记录常见的排序方法
插入排序
直接插入排序
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