十大排序算法:冒泡排序,选择排序,插入排序,希尔排序,快速排序,归并排序,基数排序,桶排序(箱排序),堆排序。
提示:所有代码都加了打印测试,看上去代码会较多一点,实际核心代码数只有几行。
1.冒泡排序(六行)
#include <stdio.h>
#define NUM 10
#if 0
void Bubble_sort(int * arr) { //普通版本
for( int i = 0; i < NUM - 1; i ++ ) {
for( int j = 0; j < NUM - 1 - i; j ++ ) {
if(arr[j + 1] < arr[j]) {
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
# else
void Bubble_sort(int * arr) { //优化版,特定情况减少排序次数
int lastExchangeIdx = 0; //记录最后一次交换的位置
int unsortBorder = NUM - 1; //记录无序数组的边缘位置
for( int i = 0; i < NUM - 1; i ++ ) {
bool IsSort = true; //判断次数循环是否一直处于有序状态,若是说明不用继续了,直接退出
for ( int j = 0; j < unsortBorder; j ++ ) {
if(arr[j + 1] < arr[j]) {
IsSort = false;
int tmp = arr[j + 1] ;
arr[j + 1] = arr[j];
arr[j] = tmp;
lastExchangeIdx = j;
}
}
unsortBorder = lastExchangeIdx;
if(IsSort) { //如果一直都没有调整过位置,说明已经有序了。
break;
}
}
}
void print_test(int * arr, int isfirst) {
if(isfirst) {
printf("排序前:\n");
} else {
printf("排序后:\n");
}
for( int i = 0 ; i < 10; i ++ ) {
printf("%d\t", arr[i]);
}
printf("\n");
}
int main() {
int arr[NUM] = {1, 9, 20, 3, 58, 52, 99, 131, 22, 79};
print_test(arr,1);
Bubble_sort(arr);
print_test(arr,0);
return 0;
}
#endif
2.选择排序(六行)
#include <stdio.h>
#define NUM 10
void swap(int * arr, int a, int b) {
int temp = arr[b];
arr[b] = arr[a];
arr[a] = temp;
}
void Select_sort(int * arr) {
for(int i = 0; i < NUM - 1; i++) {
int MinIdx = i;
for(int j = i + 1; j < NUM; j++) {
if(arr[j] < arr[MinIdx]) {
MinIdx = j;
}
}
swap(arr, i, MinIdx);
}
}
void print_test(int * arr, int isfirst) {
if(isfirst) {
printf("排序前:\n");
} else {
printf("排序后:\n");
}
for( int i = 0 ; i < 10; i ++ ) {
printf("%d\t", arr[i]);
}
printf("\n");
}
int main() {
int arr[NUM] = {1, 9, 20, 3, 58, 52, 99, 131, 22, 79};
print_test(arr,1);
Select_sort(arr);
print_test(arr,0);
return 0;
}
3.插入排序(3行)
#include <stdio.h>
#define NUM 10
int k = 0;
void swap(int * arr, int a, int b) {
int temp = arr[b];
arr[b] = arr[a];
arr[a] = temp;
}
void insert_sort(int * arr) { //核心代码
for(int i = 1; i < NUM; i++) {
for(int k = i; (arr[k] < arr[k - 1]) && k != 0; k--) {
swap(arr, k, k - 1);
}
}
//上边交换太多,下边这种方式更容易体现出它的精髓
//可能会有人认为上边那种是冒泡排序,
//其实不是的,仔细想一想冒泡排序,每次都保证了最后的一位是最大的数字,这里并没有保证,而是一次一次的插入
// for(int i = 1; i < NUM; i++) {
// int tmp = arr[i];
// for(k = i; (tmp < arr[k - 1]) && k != 0; k--) {
// arr[k] = arr[k - 1];
// }
// arr[k] = tmp;
// }
}
void print_test(int * arr, int isfirst) {
if(isfirst) {
printf("排序前:\n");
} else {
printf("排序后:\n");
}
for( int i = 0 ; i < 10; i ++ ) {
printf("%d\t", arr[i]);
}
printf("\n");
}
int main() {
int arr[NUM] = {1, 9, 20, 3, 58, 52, 99, 131, 22, 79};
print_test(arr,1);
insert_sort(arr);
print_test(arr,0);
return 0;
}
4.希尔排序(7行)
// #include <bits/stdc++.h>
#include <iostream>
using namespace std;
void shell_sort(int *arr, int length){
int gpa=0,i=0,j=0;
for(gpa=length/2;gpa>=1;gpa/=2){
for(i=gpa;i<length;i++){
int temp=arr[i];
for(j=i-gpa;j>=0&&temp<arr[j];j=j-gpa){
arr[j+gpa]=arr[j];
}
arr[j+gpa]=temp;
}
}
}
int main(){
int arr[14]={2,-1,4,1,7,6,3,6,9,8,12,7,9,7};
shell_sort(arr,14);
for(int i=0;i<14;i++){
cout<<arr[i]<<" ";
}
return 0;
}
5.快速排序
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
void quickSort(int *arr,int start,int end){
if(start>=end){
return ;
}
int l=start,r=end;
int mid=(arr[(l+r)/2]);
while(l<=r){
while(arr[l]<mid){//一定不能用l<r, 必须是l<=r
l++;
}
while(arr[r]>mid){
r--;
}
if(l<=r){ //这个if一定不能少,因为l可能会在mid的右边出现
//若交换,可能把小的换到后边,大的换到前边。
swap(arr[l],arr[r]);
l++;r--;
}
}
quickSort(arr,start,r);
quickSort(arr,l,end);
}
int main(){
// int arr[10]={2,-1,4,9,5,6,12,3,1,7};
int arr[14]={2,-1,4,1,7,6,3,6,9,8,12,7,9,7};
quickSort(arr,0,13);
for(int i=0;i<14;i++){
cout<<arr[i]<<" ";
}
return 0;
}
6.归并排序
#include <bits/stdc++.h>
using namespace std;
void MergeTwoIntervals(int *arr,int l1,int r1,int l2,int r2){
int *temp=(int *)malloc(sizeof(int)*(r2-l1+1));
int i=l1,j=l2,k=0;
while(i<=r1||j<=r2){
if((j>r2)||(i<=r1&&arr[i]<=arr[j])){
temp[k++]=arr[i++];
}else{
temp[k++]=arr[j++];
}
}
for(int i=l1;i<=r2;i++){
arr[i]=temp[i-l1];
}
free(temp);
}
void MergeSort(int* arr,int l,int r){
if(l >= r){
return ;
}
int mid = (l + r)/2;
MergeSort(arr,l,mid);
MergeSort(arr,mid+1,r);
MergeTwoIntervals(arr,l,mid,mid+1,r);
}
int main(){
int arr[14]={2,-1,4,1,7,6,3,6,9,8,12,7,9,7};
MergeSort(arr,0,13);
for(int i=0;i<14;i++){
cout<<arr[i]<<" ";
}
return 0;
}
7.基数排序(9行)
#include <stdio.h>
#include <stdlib.h>
void radix_sort( int *arr, int len, int MaxNum ) {
int * pattern = (int *)malloc(sizeof(int)*(MaxNum+1)); //因为没有用下标0,所以多开一个空间。
for( int i = 0 ; i < MaxNum + 1; i ++ ) {
pattern[i] = -1;
}
for( int i = 0; i < len ;i ++ ) {
pattern[arr[i]] = arr[i];
}
int k = 0;
for( int i = 0 ; i < MaxNum + 1; i ++ ) {
if( pattern[i] != -1 ) {
arr[k++] = pattern[i];
}
}
}
void print_test(int * arr, int isfirst) {
if(isfirst) {
printf("排序前:\n");
} else {
printf("排序后:\n");
}
for( int i = 0 ; i < 10; i ++ ) {
printf("%d\t", arr[i]);
}
printf("\n");
}
int main() {
int arr[10] = {1, 9, 20, 3, 58, 52, 99, 131, 22, 79};
print_test(arr,1);
radix_sort(arr,10, 131);
print_test(arr,0);
return 0;
}
8.计数排序(7行)
#include <stdio.h>
#include <stdlib.h>
#define NUM 10
void count_sort(int *arr, int MaxNum) {
int * pattern = (int *)calloc(sizeof(int), MaxNum + 1); //calloc分配空间帮你初始化为0
for(int i = 0; i < NUM; i++) {
pattern[arr[i]] ++;
}
int k = 0;
for(int i = 0; i < MaxNum + 1; i++) {
if(pattern[i] != 0) {
arr[k++] = i;
}
}
}
void print_test(int * arr, int isfirst) {
if(isfirst) {
printf("排序前:\n");
} else {
printf("排序后:\n");
}
for( int i = 0 ; i < 10; i ++ ) {
printf("%d\t", arr[i]);
}
printf("\n");
}
int main() {
int arr[NUM] = {1, 9, 20, 3, 58, 52, 99, 131, 22, 79};
print_test(arr,1);
count_sort(arr,131);
print_test(arr,0);
return 0;
}
9.桶排序(箱排序)
#include <stdio.h>
#include <stdlib.h>
#define NUM 10 //需要排序的数字个数
#define RANGE 10e3 //需要排序的数字最大的数字的次幂
void bucket_sort(int * arr, int len , int range) {
int idx = 0;
for( int i = 1; i < range ; i *= 10 ) {
int * pattern = (int *)malloc (sizeof(int)*len*10);
for( int i = 0;i < len*10 ; i ++ ) {
pattern[i] = -1;
}
for( int j = 0; j < len ; j ++ ) {
idx = arr[j]/i%10;
*(pattern+idx*10+j) = arr[j];
}
int k = 0;
for( int h = 0; h < len*10 ; h ++ ) {
if(pattern[h] != -1) {
arr[k++] = pattern[h];
}
}
}
}
void print_test(int * arr, int isfirst) {
if(isfirst) {
printf("排序前:\n");
} else {
printf("排序后:\n");
}
for( int i = 0 ; i < NUM; i ++ ) {
printf("%d\t", arr[i]);
}
printf("\n");
}
int main() {
int arr[NUM] = {1, 9, 20, 3, 58, 52, 99, 131, 22, 79};
print_test(arr,1);
bucket_sort(arr, NUM, RANGE);
print_test(arr,0);
return 0;
}
10.堆排序
#include <stdio.h>
#include <stdlib.h>
int size = 0;
void heap_sort(int * heap, int val) {
int hole = size ++ ;
int parent = 0;
for(; hole > 0 ; hole = parent) {
parent = (hole - 1) / 2;
if(heap[parent] < val) {
break;
}
heap[hole] = heap[parent];
}
heap[hole] = val;
}
void pop(int * heap) {
int tmp = heap[0];
heap[0] = heap[--size];
heap[size] = tmp;
tmp = heap[0]; //这步不能少
//调整
int parent = 0;
int child = 0;
for(; (parent * 2 + 1) <= (size - 1); parent = child) {
child = parent * 2 + 1;
if((child < size - 1 ) && heap[child + 1] < heap[child]) {
child += 1;
}
if(heap[child] < tmp) {
heap[parent] = heap[child];
} else {
break;
}
}
heap[parent] = tmp;
}
void print_test(int * arr, int isfirst) {
if(isfirst) {
printf("排序前:\n");
} else {
printf("排序后:\n");
}
for( int i = 0 ; i < 10; i ++ ) {
printf("%d\t", arr[i]);
}
printf("\n");
}
int main() {
int arr[10] = {1, 9, 20, 3, 58, 52, 99, 131, 22, 79};
print_test(arr,1);
int * heap = (int *)malloc(sizeof(int) * 10);
for(int i = 0 ; i < 10; i ++ ) {
heap[i] = -1;
}
for( int i = 0; i < 10; i ++ ) {
heap_sort(heap, arr[i]); //建堆
}
for(int i = 0; i < 10; i ++ ) {
pop(heap); //依次取出,形成有序数组,不过因为这里用的是小顶堆,所以是降序
}
print_test(heap,0); //打印测试
return 0;
}