以下代码实现了基本的排序算法,包括:二分插入排序、选择排序、冒泡排序、快速排序、归并排序、基数排序和计数排序七种常见的排序算法。
// Filename: sort.h
// Created by lbt on 2020-9-20.
// Description: head file of sort algorithm
#ifndef SORT_SORT_H
#define SORT_SORT_H
void InsertSort(int a[], int n);
void BubbleSort(int a[], int n);
void QuickSort(int a[], int left, int right);
void SelectionSort(int a[], int n);
void MergeSort(int a[], int low, int high);
void CountSort(int a[], int n);
#endif //SORT_SORT_H
// Filename: sort.c
// Created by lbt on 2020-9-20.
// Description: source file of sort algorithm
#include <malloc.h>
#include <stdio.h>
#include "sort.h"
// 二分查找目标元素插入位置。
// 输入: int a[], 待插入数组;
// int n, 有序部分长度;
// target, 待插入元素。
// 输出: int, 适合 target 插入的位置下标。
int SearchIndex(int a[], int n, int target){
int index = n;
int left = 0, right = n - 1;
while(left <= right){
int mid = (left + right) / 2;
if(a[mid] > target){
index = mid;
right = mid - 1;
}
else{
left = mid + 1;
}
}
return index;
}
// 将 target 插入到 a[index] 的位置。
// 输入: int a[], 待插入数组;
// int index, 插入位置;
// int n, 有序区长度;
// int target, 待插入目标。
// 输出: 无。
void InsertInto(int a[], int index, int n, int target){
int i;
for(i = index; i < n; i++){
int temp = a[i];
a[i] = target;
target = temp;
}
a[n] = target;
}
// 二分插入排序。
// 输入: int a[], 待排序数组;
// int n, 数组长度。
// 输出: 无。
void InsertSort(int a[], int n){
int i;
for(i = 1; i < n; i++){
int index = SearchIndex(a, i, a[i]);
InsertInto(a, index, i, a[i]);
}
}
// 冒泡排序。
// 输入: int a[], 待排序数组;
// int n, 数组长度。
// 输出: 无。
void BubbleSort(int a[], int n){
int i, j;
for(i = 0; i < n; i++){
int exchange = 0;
for(j = 0; j < n - 1; j++){
if(a[j] > a[j + 1]){
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
exchange = 1;
}
}
if(exchange == 0){
return;
}
}
}
// 交换数组的两个元素 a[i] 和 a[j]。
// 输入: int a[], 数组 a;
// int i, 数组下标;
// int j, 数组下标。
// 输出: 无。
void Swap(int a[], int i, int j){
if(i != j){
a[i] = a[i] + a[j];
a[j] = a[i] - a[j];
a[i] = a[i] - a[j];
}
}
// 快速排序一趟。
// 输入: int a[], 待排序数组;
// int left, 待排序区间左端点;
// int right, 待排序区间右端点。
// 输出: int, 快排一趟结束后基准数的下标。
int Partition(int a[], int left, int right){
int i = left, j = right;
int temp = a[i];
while(i < j){
while(i < j && a[j] >= temp){
j--;
}
while(j > i && a[i] <= temp){
i++;
}
Swap(a, i, j);
}
Swap(a, left, i);
return i;
}
// 快速排序。
// 输入: int a[], 待排序数组;
// int left, 待排序区间左端点;
// int right, 待排序区间右端点。
// 输出: 无。
void QuickSort(int a[], int left, int right){
int index;
if(left < right){
index = Partition(a, left, right);
QuickSort(a, index + 1, right);
QuickSort(a, left, index - 1);
}
}
// 选择排序。
// 输入: int a[], 待排序数组;
// int n, 数组长度。
// 输出: 无。
void SelectionSort(int a[], int n){
int i, j;
for(i = 0; i < n; i++){
int min_index = i;
for(j = i; j < n; j++){
if(a[j] < a[min_index]){
min_index = j;
}
}
if(min_index != i){
int temp = a[i];
a[i] = a[min_index];
a[min_index] = temp;
}
}
}
// 合并数组内的两个连续的递增序列。
// 输入: int a[], 带合并序列所在数组;
// int low, 第一个递增序列起始下标;
// int mid, 第一个有序序列尾元素下标;
// int high, 第二个有序序列尾元素下标。
// 输出: 无。
void Merge(int a[], int low, int mid, int high){
int *temp = malloc(sizeof(int) * (high - low + 1)); // 保存合并结果
int index;
int i = low, j = mid + 1; // i 为序列1 起始下标, j 为序列2 起始下标
for(index = 0; index <= high - low; index++){
if(i <= mid && j <= high){ // 两个序列中都有元素
if(a[i] < a[j]){ // 取两个序列中较小的元素,下标后移
temp[index] = a[i++];
}else{
temp[index] = a[j++];
}
}
else if(i <= mid){ // 序列2 完,序列1 还有元素,直接复制到 temp
temp[index] = a[i++];
}
else if(j <= high){ // 序列1 完,序列2 还有元素,直接赋值到 temp
temp[index] = a[j++];
}
}
for(index = 0; index <= high - low; index++){
a[low + index] = temp[index];
}
free(temp);
return;
}
// 归并排序。
// 输入: int a[], 待排序数组;
// int low, 待排序部分最小下标;
// int high, 待排序部分最大下标。
// 输出: 无。
void MergeSort(int a[], int low, int high){
if(low < high){
int mid = (low + high) / 2;
MergeSort(a, low, mid);
MergeSort(a, mid + 1, high);
Merge(a, low, mid, high);
}
return;
}
// 找出数组中的最小元素。
// 输入: int a[], 待查找数组;
// int n, 数组长度。
// 输入: int, 数组 a 中的最小元素值。
int Min(int a[], int n){
int i, min = a[0];
for(i = 0; i < n; i++){
if(a[i] < min){
min = a[i];
}
}
return min;
}
// 找出数组中的最大元素。
// 输入: int a[], 待查找数组;
// int n, 数组长度。
// 输入: int, 数组 a 中的最大元素值。
int Max(int a[], int n){
int i, max = a[0];
for(i = 0; i < n; i++){
if(a[i] > max){
max = a[i];
}
}
return max;
}
// 计数排序。
// 输入: int a[], 待排序数组;
// int n, 数组长度。
// 输出: 无。
void CountSort(int a[], int n){
if(n < 1){
return;
}
int min = Min(a, n);
int max = Max(a, n);
int *count_array = malloc(sizeof(int) * (max - min + 1));
int i;
for(i = 0; i <= max - min; i++){
count_array[i] = 0;
}
for(i = 0; i < n; i++){
int index = a[i] - min;
count_array[index]++;
}
int j = 0;
i = 0;
while(i < n){
while(count_array[j] != 0){
a[i++] = min + j;
count_array[j]--;
}
j++;
}
return;
}
// Filename: main.c
// Created by lbt on 2020-9-20.
// Description: test sort algorithm
#include <stdio.h>
#include "sort.h"
int main() {
int i;
// int a[10];
// int a_len = sizeof(a) / sizeof(int);
// for(i = 0; i < a_len; i++){
// a[i] = 10 - i;
// }
int *a;
int a_len = sizeof(a) / sizeof(int);
if(a == NULL){
a_len = 0;
}
SelectionSort(a, a_len);
BubbleSort(a, a_len);
QuickSort(a, 0, a_len - 1);
InsertSort(a, a_len);
MergeSort(a, 0, a_len - 1);
CountSort(a, a_len);
for(i = 0; i < a_len; i++){
printf("%d\t", a[i]);
}
}