随便先发点东西吧,慢慢记录。。
从排序开始,毕竟去年我倒在了排序上。
选择排序,冒泡排序,快速排序,归并排序,计数排序————5个排序
这里的例子都是从小到大的,c语言。
我觉得一般情况下应该够用了吧,不够的话以后在学。。。
选择排序
应该是最简单的排序方式了吧?
void SelectSort(int arr[], int num) //选择排序, 每次都将最小的数字放在i位上。
{
int temp;
for (int i = 0; i < num; i++) {
for (int j = i + 1; j < num; j++) {
if (arr[i] > arr[j]) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}
冒泡排序
谭浩强书上的第2个排序算法,还是比较好理解的,和选择排序一样主要都是注意循环的开始和条件。
void BubbleSort(int arr[], int num) //冒泡排序,两两比较,每次都把小的放前面
{
int temp;
for (int i = 0; i < num; i++) { //每次循环后数列的最后(num - j)位会变成还未排序的数字中的最大值
for (int j = 0; j < num-i-1; j++) {
if(arr[j] > arr[j + 1])
{
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
快速排序
找一个基准数,把小于它的放左边,大于它的放右边。
然后把在左边的元素作为一个数组拿出来,重复上面的操作,右边同理。这样一直重复到两边被挑出来的数组中的元素少于两个
void QuickSort(int arr[],int left, int right) //快速排序
{
if (left >= right) { //当区域内的元素少于两个时此区域 无法排序/已经排序完成 。
return ;
}
int temp, i, j, pivot;
pivot = arr[right]; //基准数,每次都用数组的最后一个元素作为基准数
i = left; //标记位,标记较小的元素应该放置的位置
for (j = left; j < right; j++) {
if (arr[j] < pivot) { //如果元素小于基准数,那么将其移动到从left开始的左边
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
}
}
temp = arr[i]; //将基准数移动到i的位置,此时,左边的所有数都小于基准数,右边的所有数都大于基准数
arr[i] = pivot;
arr[right] = temp;
QuickSort(arr, left, i - 1); //用同样的方法处理基准数左边的所有元素
QuickSort(arr, i + 1, right); //用同样的方法处理基准数右边的所有元素
}
归并排序
由两个函数组成,调用的时候调用MergeSort()。
用网上的图片来解释吧。绿色的数字是在程序中执行的顺序。
就是把数组分分分,分到单个元素,然后把相邻的两个 数组/元素 排序合在一起,合合合再合回去。
MergeSort()是用来把数组分成两个,以及调用merge()的。
merge()用来将在上一个数组被分出来的两个数组排序的。
void merge(int arr[], int left, int middle, int right)
{
int i, j, k;
int n1 = middle - left + 1; //前半段的数组的元素的个数
int n2 = right - middle; //后半段的数组的元素的个数
int L[n1], R[n2]; //用于保存两个数组
for (i = 0; i < n1; i++) {
L[i] = arr[left + i];
}
for (i = 0; i < n2; i++) {
R[i] = arr[middle + 1 + i];
}
i = 0; //前半段L数组的指针位置/标记位
j = 0; //后半段R数组的指针位置/标记位
k = left; //位于原数组上的指针位置/标记位
while(i < n1 && j < n2) //将被标记的两个元素中小的那个放在原数组的标记位上
{ //并将指向较小元素的指针和指向原数组的指针分别加一。
if (L[i] < R[j]) { //当两者中任一数组的所有元素被放回了原数组,那么结束循环
arr[k++] = L[i++];
// i++;
} else {
arr[k++] = R[j++];
// j++;
}
// k++;
}
while(i < n1) //将另一个数组中的剩余元素放回原数组
{
arr[k++] = L[i++];
}
while(j < n2)
{
arr[k++] = R[j++];
}
}
void MergeSort(int arr[], int left, int right)
{
if (left < right) { //当区域内的元素少于两个时此区域 无法排序/已经排序完成 。
int middle = left + ( right - left ) / 2; //分界元素的位置,即从left到middle(包括middle)在内都是
//前半段的数组,从middle+1开始到right都是后半段
MergeSort(arr, left, middle); //对前半段进行同样的处理/排序
MergeSort(arr, middle + 1, right); //处理/排序后半段
merge(arr, left, middle, right); //排序
}
}
计数排序
没有用比较,但很厉害啊我觉得。
建立一个数组,用来记住每个元素出现的次数,再依次放回去。
//在C中使用要引入stdlib.h和string.h两个库。
void CountSort(int arr[],int num)
{
int min = arr[0], max = arr[0];
int i, j = 0;
for (i = 0; i < num; i++) { //找到数组的最大值与最小值
if (arr[i] < min) {
min = arr[i];
}
if (arr[i] > max) {
max = arr[i];
}
}
int sum = max - min + 1; //假设最大值最小值之间所有整数都存在的话,那么共有这么多数
// int *temp = (int*) malloc(sizeof(int) * sum);
// memset(temp, 0, sum*sizeof(int)); //将数组的所有值设置为0
//memset()的用途是将temp地址后面的sum*sizeof(int)个字节长度的空间的值设置为0(也就是第2个参数的值)
int *temp = calloc(sum, sizeof(int)); //动态分配,创建一个 数组/指针 用来存数组中每个元素的出现次数,calloc会把每个元素默认设置为0
for (i = 0; i < num; i++) { //元素每出现一次,那么就在temp数组相应的位置加一
temp[arr[i] - min]++;
}
for ( i = 0; i < sum; i++) { //temp中每个元素的值就是(下标+min)的出现次数,从小到大放回原数组里
while(temp[i]-- > 0)
{
arr[j++] = i + min;
}
}
free(temp); //释放动态空间
}
5个排序的总集,还有用来测试的傻乎乎的代码
// 部分排序算法的训练和模版
//
// c语言
#include <stdio.h>
#include <string.h> //计数排序中的memset()函数
#include <stdlib.h> //计数排序中的free()函数
void SelectSort(int arr[], int num) //选择排序, 每次都将最小的数字放在i位上。
{
int temp;
for (int i = 0; i < num; i++) {
for (int j = i + 1; j < num; j++) {
if (arr[i] > arr[j]) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
printf("SelectSort:\n");
}
void BubbleSort(int arr[], int num) //冒泡排序,两两比较,每次都把小的放前面
{
int temp;
for (int i = 0; i < num; i++) { //每次循环后数列的最后(num - j)位会变成还未排序的数字中的最大值
for (int j = 0; j < num - i; j++) {
if(arr[j] > arr[j + 1])
{
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
printf("BubbleSort:\n");
}
void QuickSort(int arr[],int left, int right) //快速排序
{
if (left >= right) { //当区域内的元素少于两个时此区域 无法排序/已经排序完成 。
return ;
}
int temp, i, j, pivot;
pivot = arr[right]; //基准数,每次都用数组的最后一个元素作为基准数
i = left; //标记位,标记较小的元素应该放置的位置
for (j = left; j < right; j++) {
if (arr[j] < pivot) { //如果元素小于基准数,那么将其移动到从left开始的左边
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
}
}
temp = arr[i]; //将基准数移动到i的位置,此时,左边的所有数都小于基准数,右边的所有数都大于基准数
arr[i] = pivot;
arr[right] = temp;
QuickSort(arr, left, i - 1); //用同样的方法处理基准数左边的所有元素
QuickSort(arr, i + 1, right); //用同样的方法处理基准数右边的所有元素
}
void merge(int arr[], int left, int middle, int right)
{
int i, j, k;
int n1 = middle - left + 1; //前半段的数组的元素的个数
int n2 = right - middle; //后半段的数组的元素的个数
int L[n1], R[n2]; //用于保存两个数组
for (i = 0; i < n1; i++) {
L[i] = arr[left + i];
}
for (i = 0; i < n2; i++) {
R[i] = arr[middle + 1 + i];
}
i = 0; //前半段L数组的指针位置/标记位
j = 0; //后半段R数组的指针位置/标记位
k = left; //位于原数组上的指针位置/标记位
while(i < n1 && j < n2) //将被标记的两个元素中小的那个放在原数组的标记位上
{ //并将指向较小元素的指针和指向原数组的指针分别加一。
if (L[i] < R[j]) { //当两者中任一数组的所有元素被放回了原数组,那么结束循环
arr[k++] = L[i++];
// i++;
} else {
arr[k++] = R[j++];
// j++;
}
// k++;
}
while(i < n1) //将另一个数组中的剩余元素放回原数组
{
arr[k++] = L[i++];
}
while(j < n2)
{
arr[k++] = R[j++];
}
}
void MergeSort(int arr[], int left, int right)
{
if (left < right) { //当区域内的元素少于两个时此区域 无法排序/已经排序完成 。
int middle = left + ( right - left ) / 2; //分界元素的位置,即从left到middle(包括middle)在内都是
//前半段的数组,从middle+1开始到right都是后半段
MergeSort(arr, left, middle); //对前半段进行同样的处理/排序
MergeSort(arr, middle + 1, right); //处理/排序后半段
merge(arr, left, middle, right); //排序
}
}
void CountSort(int arr[],int num)
{
int min = arr[0], max = arr[0];
int i, j = 0;
for (i = 0; i < num; i++) { //找到数组的最大值与最小值
if (arr[i] < min) {
min = arr[i];
}
if (arr[i] > max) {
max = arr[i];
}
}
int sum = max - min + 1; //假设最大值最小值之间所有整数都存在的话,那么共有这么多数
// int *temp = (int*) malloc(sizeof(int) * sum);
// memset(temp, 0, sum*sizeof(int)); //将数组的所有值设置为0
//memset()的用途是将temp地址后面的sum*sizeof(int)个字节长度的空间的值设置为0(也就是第2个参数的值)
int *temp = calloc(sum, sizeof(int)); //动态分配,创建一个 数组/指针 用来存数组中每个元素的出现次数,calloc会把每个元素的值设置为0
for (i = 0; i < num; i++) { //元素每出现一次,那么就在temp数组相应的位置加一
temp[arr[i] - min]++;
}
for ( i = 0; i < sum; i++) { //temp中每个元素的值就是(下标+min)的出现次数,从小到大放回原数组里
while(temp[i]-- > 0)
{
arr[j++] = i + min;
}
}
free(temp); //释放动态空间
printf("CountSort:\n");
}
int main()
{
// int arr[10] = {5,6,4,10,2,1,9,8,7,3}; //用于测试的两组数据。
int arr[10] = {52,76,43,42,98,76,74,99,101,32};
SelectSort(arr, 10);
// BubbleSort(arr, 10);
// printf("QuickSort:\n");
// QuickSort(arr, 0, 9);
// printf("MergeSort:\n");
// MergeSort(arr, 0, 9);
// CountSort(arr, 10);
for (int i = 0; i < 10; i++) { //输出,来检查排序是否正确
printf("%d ",arr[i]);
}
printf("\n");
return 0;
}