常见排序算法实现
冒泡排序
实现1
/*
* 冒泡排序的核心逻辑
* 1.遍历数组,每一次都将数组的最大或最小值放到数组最后
* 2.控制这个循环的最大值,第一次等于len-1,第二次等于len-2,直到等于1
* 3.构造符合上述条件的一个输入,将每一次的输入作为核心循环的最大值
*/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ARR_MAX 10
void bubbleSort(int arr[], int len);
void printArr(int arr[], int len);
int main()
{
int arr[ARR_MAX], len;
len = sizeof(arr) / sizeof(*arr);
srand(time(NULL));
for (int i = 0; i < len; i++) {
arr[i] = rand() % 100;
}
printf("原始序列: ");
printArr(arr, len);
printf("排序序列: ");
bubbleSort(arr, len);
printArr(arr, len);
return 0;
}
void bubbleSort(int arr[], int len)
{
int i, j, num;
for (i = 0; i < len - 1; i++) {
for (j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j+1]) {
num = arr[j+1];
arr[j+1] = arr[j];
arr[j] = num;
}
}
}
return;
}
void printArr(int arr[], int len)
{
int i;
for(i = 0; i < len; i++) {
printf("%d ",arr[i]);
}
printf("\n");
return;
}
实现2
/*
* 冒泡排序的核心逻辑
* 1.遍历数组,每一次都将数组的最大或最小值放到数组最后
* 2.控制这个循环的最大值,第一次等于len-1,第二次等于len-2,直到等于1
* 3.构造符合上述条件的一个输入,将每一次的输入作为核心循环的最大值
*/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ARR_MAX 10
void bubbleSort(int arr[], int len);
void printArr(int arr[], int len);
int main()
{
int arr[ARR_MAX], len;
len = sizeof(arr) / sizeof(*arr);
srand(time(NULL));
for (int i = 0; i < len; i++) {
arr[i] = rand() % 100;
}
printf("原始序列: ");
printArr(arr, len);
printf("排序序列: ");
bubbleSort(arr, len);
printArr(arr, len);
return 0;
}
void bubbleSort(int arr[], int len)
{
int i, j, num;
i = len - 1;
while (i != 0) {
for (j = 0; j < i; j++) {
if (arr[j] > arr[j+1]) {
num = arr[j+1];
arr[j+1] = arr[j];
arr[j] = num;
}
}
i--;
}
return;
}
void printArr(int arr[], int len)
{
int i;
for(i = 0; i < len; i++) {
printf("%d ",arr[i]);
}
printf("\n");
return;
}
选择排序
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ARR_MAX 10
void PrintArr(int arr[], int len);
void SelectionSortUp(int arr[], int len);
void SelectionSortDown(int arr[], int len);
int main()
{
int arr[ARR_MAX], len;
len = sizeof(arr) / sizeof(*arr);
srand(time(NULL));
for (int i = 0; i < len; i++) {
arr[i] = rand() % 100;
}
printf("原始序列: ");
PrintArr(arr, len);
printf("排序序列: ");
SelectionSortUp(arr, len);
PrintArr(arr, len);
return 0;
}
/* 升序排序 */
void SelectionSortUp(int arr[], int len)
{
int i, j, num;
for (i = len - 1; i > 0 ; i--) {
for (j = 0; j < (i - 1); j++) {
if (arr[j] > arr[i]) {
num = arr[i];
arr[i] = arr[j];
arr[j] = num;
}
}
}
return;
}
/* 降序排序 */
void SelectionSortDown(int arr[], int len)
{
int i, j, num;
for (i = 0; i < len-1 ; i++) {
for (j = i; j < len; j++) {
if (arr[j] > arr[i]) {
num = arr[i];
arr[i] = arr[j];
arr[j] = num;
}
}
}
return;
}
void PrintArr(int arr[], int len)
{
int i;
for(i = 0; i < len; i++) {
printf("%d ",arr[i]);
}
printf("\n");
return;
}
直接插入排序
实现1
/* 1.直接插入排序的基本思想是,首先将整个数组分为无序序列和有序序列两部分
* 2.然后将无序序列中的数据插入到有序的序列中合适的位置
* 3.在遍历无序序列时,首先拿无序序列中的首元素去与有序序列中的每一个元素比较并插入到合适的位置,一直到无序序列中的所有元素插完为止
*/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ARR_MAX 10
void PrintArr(int arr[], int len);
void InsertionSort(int arr[], int len);
int main()
{
int arr[ARR_MAX], len;
len = sizeof(arr) / sizeof(*arr);
srand(time(NULL));
for (int i = 0; i < len; i++) {
arr[i] = rand() % 100;
}
printf("原始序列: ");
PrintArr(arr, len);
printf("排序序列: ");
InsertionSort(arr, len);
PrintArr(arr, len);
return 0;
}
void InsertionSort(int arr[], int len)
{
int i, j, num;
/*
* 1.以i为分界,i之前为有序序列,i之后为无序序列
* 2.特殊的arr[0]默认属于有序序列
*/
for (i = 1; i < len; i++) {
/* 将无序序列的第一个元素取出赋值给num */
num = arr[i];
/*
* 1.从后向前遍历有序序列,即区间[0,i-1]
* 2.依次比较有序序列中的值与num的值,将大于num的元素后移一位,即进行升序排序
* 3.后移元素会覆盖有序序列后的无序序列第一个元素的位置,即arr[i]
* 4.由于后移操作为简单的复制,而非元素交换,所以后的同时有序序列中会产生一个重复值,即arr[j]
* 6.循环结束后,此时有序序列中所有大于num的元素全部后移一位,原本num的位置被覆盖,arr[j]的位置为向有序列表中新插入值的位置
*/
for (j = i-1; j >= 0 && arr[j] > num; j--) {
arr[j+1] = arr[j];
}
/*
* 1.在此前循环中j--,故此处需要j+1
* 2.将原本的num值放入,有序序列长度+1,无序序列长度-1
*/
arr[j+1] = num;
}
return;
}
void PrintArr(int arr[], int len)
{
int i;
for(i = 0; i < len; i++) {
printf("%d ",arr[i]);
}
printf("\n");
return;
}
实现2
/* 1.直接插入排序的基本思想是,首先将整个数组分为无序序列和有序序列两部分
* 2.然后将无序序列中的数据插入到有序的序列中合适的位置
* 3.在遍历无序序列时,首先拿无序序列中的首元素去与有序序列中的每一个元素比较并插入到合适的位置,一直到无序序列中的所有元素插完为止
*/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ARR_MAX 10
void PrintArr(int arr[], int len);
void InsertionSort(int arr[], int len);
int main()
{
int arr[ARR_MAX], len;
len = sizeof(arr) / sizeof(*arr);
srand(time(NULL));
for (int i = 0; i < len; i++) {
arr[i] = rand() % 100;
}
printf("原始序列: ");
PrintArr(arr, len);
printf("排序序列: ");
InsertionSort(arr, len);
PrintArr(arr, len);
return 0;
}
void InsertionSort(int arr[], int len)
{
int i, j, n, num;
for (i = 1; i < len; i++) {
num = arr[i];
j = i-1;
n = j;
while(j >= 0) {
if(arr[n] > num) {
arr[n+1] = arr[n];
n--;
}
j--;
}
arr[n+1] = num;
}
return;
}
void PrintArr(int arr[], int len)
{
int i;
for(i = 0; i < len; i++) {
printf("%d ",arr[i]);
}
printf("\n");
return;
}
计数排序
实现1
/*
* 计数排序基本思想:将无序序列转换成一个一维线性数组例如无序序列元素最大100
* 1.无序序列最大元素为100则开辟一个100长度的数组,将对应下标元素的值+1对应无序序列元素对应有序序列中对应的位置
* 2.反向填充,得到有序序列数组
*
* 缺陷:空间换时间的思路,存在大量空间浪费,负数元素需偏移后进行处理
*/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ARR_LEN 10
#define ARR_MAX 100
void PrintArr(int arr[], int len);
void CountingSort(int *IniArr, int *SortedArr, int n);
int main()
{
int arr[ARR_LEN], SortedArr[ARR_LEN], len;
len = sizeof(arr) / sizeof(*arr);
/*填充随机值*/
srand(time(NULL));
for (int i = 0; i < len; i++) {
arr[i] = rand() % 100;
}
printf("原始序列: ");
PrintArr(arr, len);
CountingSort(arr, SortedArr, len);
printf("排序序列: ");
PrintArr(SortedArr, len);
return 0;
}
void CountingSort(int IniArr[], int *SortedArr, int n)
{
int count_arr[ARR_MAX] = {0};
int num;
for (int i = 0; i < n; i++) {
count_arr[IniArr[i]]++;
}
for (int k = 1; k < ARR_MAX; k++) {
count_arr[k] += count_arr[k - 1];
}
for (int j = n -1; j > 0; j--){
num = count_arr[IniArr[j]];
SortedArr[--num] = IniArr[j];
}
return;
}
void PrintArr(int arr[], int len)
{
int i;
for(i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return;
}
实现2
/*
* 计数排序基本思想:将无序序列转换成一个一维线性数组例如无序序列元素最大100
* 1.无序序列最大元素为100则开辟一个100长度的数组,将对应下标元素的值+1对应无序序列元素对应有序序列中对应的位置
* 2.反向填充,得到有序序列数组
*
* 缺陷:空间换时间的思路,存在大量空间浪费,负数元素需偏移后进行处理
*/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ARR_LEN 10
#define ARR_MAX 100
void PrintArr(int arr[], int len);
void CountingSort(int arr[], int len);
int main()
{
int arr[ARR_LEN], SortedArr[ARR_LEN], len;
len = sizeof(arr) / sizeof(*arr);
/*填充随机值*/
srand(time(NULL));
for (int i = 0; i < len; i++) {
arr[i] = rand() % 100;
}
printf("原始序列: ");
PrintArr(arr, len);
CountingSort(arr, len);
return 0;
}
void CountingSort(int arr[], int len)
{
int SortedArr[ARR_MAX] = {0};
for (int i = 0; i < len; i++) {
SortedArr[arr[i]]++;
}
printf("排序序列: ");
for (int j = 0; j < ARR_MAX; j++) {
while(SortedArr[j] == 1) {
printf("%d ", j);
break;
}
}
return;
}
void PrintArr(int arr[], int len)
{
int i;
for(i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return;
}
基数排序
/*
* 基数排序基本思想:将无序序列中的元素每次取出个位的值,然后根据取出的值进行排序,然后在此基础上取十位的值再次排序,直到最高位数结束
* 由于每次排序是根据某个位数进行排序的,所以可以避免计数排序的一些弊端,可将基数排序看作是计数排序的一种改良
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#define ARR_MAX 10
void PrintArr(int arr[], int len);
int ArrMaxBit(int data[], int len);
void RadixSort(int arr[], int len);
int main()
{
int arr[ARR_MAX], len;
len = sizeof(arr) / sizeof(*arr);
/* 填充随机值 */
srand(time(NULL));
for(int i = 0; i < len; i++) {
arr[i] = rand() % 100;
}
printf("原始序列: ");
PrintArr(arr, len);
RadixSort(arr, len);
printf("排序序列: ");
PrintArr(arr, len);
return 0;
}
void RadixSort(int arr[], int len)
{
int BucketLen, MaxBit;
int bucket[10] = {0};
int *SortedArr;
/* 新建一个与arr长度相同的数组,动态申请内存 */
SortedArr = (int *)malloc(sizeof(int *) * len);
BucketLen = sizeof(bucket) / sizeof(*bucket);
MaxBit = ArrMaxBit(arr, len);
int bits = 1;
int j;
for(int i = 0; i < MaxBit; i++) {
memset(bucket, 0, (sizeof(*bucket) * BucketLen));
/* 记录每一位上,每个数字出现的次数 */
int BucketNum;
for(j = 0; j < len; j++) {
BucketNum = (arr[j] / bits) % 10;
bucket[BucketNum]++;
}
/* 算出每个元素在有序序列中的序号 */
for(j = 1; j < BucketLen; j++) {
bucket[j] += bucket[j - 1];
}
/* 将无序序列中的元素依照已经计算出的序号放入新数组中,同时减少桶中对应的数量 */
/* 逆序遍历防止出现大元素在前小元素在后的情况 */
for(j = len -1 ; j >= 0; j--) {
BucketNum = (arr[j] / bits) % 10;
SortedArr[bucket[BucketNum] - 1] = arr[j];
bucket[BucketNum]--;
}
for(int p = 0; p < len; p++) {
arr[p] = SortedArr[p];
}
bits = bits * 10;
}
free(SortedArr);
return;
}
/* 求数组最大元素有几位 */
int ArrMaxBit(int data[], int len)
{
int MaxNum;
MaxNum = data[0];
for (int i = 1; i < len; i++) {
if(MaxNum < data[i]) {
MaxNum = data[i];
}
}
int d=1;
while (MaxNum >= 10) {
MaxNum /= 10;
d++;
}
return d;
}
void PrintArr(int arr[], int len)
{
for(int i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("end\n");
return;
}
归并排序
/*
* 归并排序:将原始数组A[0:n-1]中的元素分成两个大小大致相同的子数组:A[0:n/2]和A[n/2+1:n-1],分别对这两个子数组单独排序
* 然后将已排序的两个数组归并成一个含有n个元素的有序数组。(不断地进行二分,直至待排序数组中只剩下一个元素为止,然后不断合并两个排好序的数组段)
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#define ARR_MAX 10
void PrintArr(int arr[], int len);
void MergeSort(int arr[], int left, int right);
int main()
{
int arr[ARR_MAX], len;
len = sizeof(arr) / sizeof(*arr);
/* 填充随机值 */
srand(time(NULL));
for (int i = 0; i < len; i++) {
arr[i] = rand() % 100;
}
printf("原始序列: ");
PrintArr(arr, len);
MergeSort(arr, 0, len - 1);
printf("排序序列: ");
PrintArr(arr, len);
return 0;
}
//合并操作的代码实现
void Merge(int arr[], int left, int mid, int right)
{
int *SortedArr;
SortedArr = (int *)malloc(right - left + 1);
int First = left;
int Last = mid + 1;
int StackTop = 0;
/*
* 将[First, mid]和[mid+1, Last]区间中的有序数组合并存入临时数组SortedArr中
*/
while (First <= mid && Last <= right) {
if (arr[First] <= arr[Last]) {
SortedArr[StackTop++] = arr[First++];
} else {
SortedArr[StackTop++] = arr[Last++];
}
}
while (First <= mid) {
SortedArr[StackTop++] = arr[First++];
}
while (Last <= right) {
SortedArr[StackTop++] = arr[Last++];
}
/*
* 回填arr并销毁临时数组
*/
for (First = left, StackTop = 0; First <= right; First++) {
arr[First] = SortedArr[StackTop++];
}
free(SortedArr);
}
//递归形式的归并排序算法
void MergeSort(int arr[], int left, int right)
{
int mid = 0;
if (left < right) {
mid = (left + right) / 2;
MergeSort(arr, left, mid);
MergeSort(arr, mid + 1, right);
Merge(arr, left, mid, right);
}
}
void PrintArr(int arr[], int len)
{
for (int i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("end\n");
return;
}
快速排序
/*
* 快速排序:采用“分治”的思想,对于一组数据,选择一个基准元素(base),通常选择第一个或最后一个元素,通过第一
* 轮扫描,比base小的元素都在base左边,比base大的元素都在base右边,再有同样的方法递归排序这两部分,直到序列
* 中所有数据均有序为止。
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#define ARR_MAX 10
void PrintArr(int arr[], int len);
void QuickSort(int arr[], int begin, int end);
int main()
{
int arr[ARR_MAX];
int len = sizeof(arr) / sizeof(*arr);
/* 填充随机值 */
srand(time(NULL));
for (int i = 0; i < len; i++) {
arr[i] = rand() % 100;
}
printf("原始序列: ");
PrintArr(arr, len);
QuickSort(arr, 0, len - 1);
printf("排序序列: ");
PrintArr(arr, len);
return 0;
}
void QuickSort(int arr[], int begin, int end)
{
if (begin > end) {
return;
}
int tmp = arr[begin];
int i = begin;
int j = end;
/*
* 优先改变尾部指针的值,保证最后头尾指针重合的位置小于哨兵位的值
*/
while (i != j) {
while (arr[j] >= tmp && j > i) {
j--;
}
while (arr[i] <= tmp && j > i) {
i++;
}
if (j > i) {
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
arr[begin] = arr[i];
arr[i] = tmp;
/*
* 此处采用双层递归,一层递归结束进入二层,在二层中在调用一层,数组并不是从中间被一分为二,而是从头尾两个
* 方向不断缩短
*/
QuickSort(arr, begin, i-1);
QuickSort(arr, i+1, end);
return;
}
void PrintArr(int arr[], int len)
{
for (int i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("end\n");
return;
}