提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
题目:
目录
(1)冒泡排序
冒泡排序的思路是数小的像泡泡一样冒出来,反过来我们可以理解为,数大的像石头一样沉下去。
我们遍历数组,从左到右,若右边的数比左边的大,则交换。
第一遍:最大的数沉下去
第二遍:第二大的数沉在倒数第二个位置
…
代码:
#include<stdio.h>
void main()
{
int n[10] = { 55,1,68,9,21,13,8,7,12,62 };//定义一个大小为10的数组
int i, j, temp;
for (i = 1; i <= 9; i++)//外层循环是比较的轮数,数组内有10个数,那么就应该比较10-1=9轮
{
for (j = 0; j <= 9 - i; j++)//内层循环比较的是当前一轮的比较次数
{
if (n[j] > n[j + 1])//相邻两个数如果逆序,则交换位置
{
temp = n[j];
n[j] = n[j + 1];
n[j + 1] = temp;
}
}
}
printf("排序过后的数顺序:\n");
for (i = 0; i < 10; i++)
printf("%-4d", n[i]);
printf("\n");
}
(2)选择排序
选择排序:选出最小的数,放在首位; 再次选,放在第二位, …
#include <stdio.h>
void arr_out(int a[8])
{
int i = 0;
for(i = 0;i < 8;i++)//输出函数
{
printf("%d ",a[i]);
}
printf("\n");
}
void arr_sort(int *p,int n)
{
int i,j;
int min = 0;
for(i = 0;i < n - 1;i++)//排序次数
{
min = i;
for(j = i + 1;j < n;j++)
{
if(p[j] < p[min])
{
min = j;//记录交换的元素下标值
}
}
if(i != min)
{
int temp = p[i];
p[i] = p[min];
p[min] = temp;
}
}
}
int main()
{
int a[8] = {0};
int i = 0;
for(i = 0;i < 8;i++)
{
scanf("%d",&a[i]);
}
arr_sort(a,8);//排序函数
arr_out(a);//输出函数
return 0;
}
(3)直接插入排序
代码:
#define _CRT_SECURE_NO_WARNINGS 1
//直接插入排序法
#include <stdio.h>
void Compare(int arr[], int len)
{
int i = 0;
for (i = 0; i < len-1; i++)//len减一因为要插入的数是i+1
{
int M = i;//记录有序列表最后应该元素下标
int num = arr[i + 1];//要插入的数
while (M >= 0)
{
if (num < arr[M])//继续比较
{
arr[M + 1] = arr[M];//交换数值
M--;
}
else
{
break;
}
}
arr[M + 1] = num;
}
}
int main()
{
int arr[] = { 2,3,4,1,2,24,4,26,3,44,4 };
int len = sizeof(arr) / 4;
int i = 0;
Compare(arr,len);
for (i = 0; i < len; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
(4)希尔排序
代码:
#include <stdio.h>
int main(int argc, char *argv[])
{
srand(time(NULL));//设置随机数种子
int i,j,k,m,temp,len;
int a[15]={0};//定义一个随机数数组并输出
printf("排序前:");
for(i=0;i<15;i++)
{
a[i]=rand()%99;
printf("%2d ",a[i]);
}
putchar('\n');
len=sizeof(a)/sizeof(a[0]);
for(m=len/2;m>0;m/=2)//m为每组成员间隔
{
for(i=0;i<m;i++)//将所有组排序一次
{
for(j=i+m;j<len;j+=m)//j定位到组中后一位元素
{
temp=a[j];//将值存储一次
k=j-m;//k是i位置下标
while(k>=0&&a[k]>temp)//进行交换数据
{
a[j]=a[k];
a[k]=temp;
k-=m;
}
}
}
}
printf("排序后:");
for(i=0;i<15;i++)//遍历数组
{
printf("%2d ",a[i]);
}
putchar('\n');
return 0;
}
(5)推排序
代码:
#include <stdio.h>
#include <stdlib.h>
#define MAXNUM 10
struct SqList{
int r[MAXNUM+1];
int length;
};
void HeapAdjust(SqList* L, int i, int j){
int temp, k;
temp = L->r[i];
for(k=2*i;k<=j;k*=2){ //沿关键字较大的孩子结点向下筛选,2i为左孩子,2i+1为右孩子
if(k<j && L->r[k] < L->r[k+1]) //左孩子比右孩子小
++k; //j为关键字中较大的记录的下标
if(temp >= L->r[k]) //如果当前值比左右孩子中最大值还大,就跳出循环,将当前值存在当前左右孩子的父节点
break; //当前值应插入在位置i上,因为值比当前左右孩子还大
//如果当前值比左右孩子中最大的还小,那么把左右孩子中大的那个数存到当前结点
L->r[i] = L->r[k];
//然后将当前值索引指向了刚刚替换的位置,后面的k*=2拿到的是左孩子
i = k;
}
//这里插入的位置如果有孩子,值一定比孩子大,如果没有孩子,一定是叶子结点,也就是说小的数会被排到后面
L->r[i] = temp; //插入
}
void swap(SqList* L, int i, int j){
int temp;
temp = L->r[i];
L->r[i] = L->r[j];
L->r[j] = temp;
}
void HeapSort(SqList* L){
int i;
for(i=L->length/2;i>0;i--) //这里从1半开始调,最后得到的堆的根结点的值最大,最后结点的值最小
HeapAdjust(L, i, L->length);
for(i=L->length;i>1;i--){ //先进行一次交换,然后再调整大顶堆,使次大数放第二个位置......
swap(L, 1, i); //交换根位置最大值和末尾未交换过的位置
HeapAdjust(L, 1, i-1); //交换完之后重新找到最大值,此时最后面已经排好的值不要加进来
}
}
int main(){
SqList* L = (SqList*)malloc(sizeof(SqList));
L->length = MAXNUM;
int a[11] = {12,6,1,3,0,7,4,5,2,8,9}; //第一个为哨兵
int i;
for(i=0;i<MAXNUM+1;i++)
L->r[i] = a[i];
//堆排序
HeapSort(L);
//打印
for(i=0;i<MAXNUM+1;i++)
printf("%d ", L->r[i]);
printf("\n");
return 0;
}
(6)桶排序
代码:
#include<stdio.h>
#include<stdlib.h>
typedef struct node *Snode;
typedef struct node{
int key;
Snode next;
}BBc;
void sort(int keys[],int keys_size,int bucket_size)
{
Snode *bucket_table = (Snode *)malloc(bucket_size*sizeof(Snode));//为结构体数组分配空间。
for(int i=0;i<bucket_size;i++)//初始化每个结构体数组单元。
{
bucket_table[i] = (Snode)malloc(sizeof(Snode));//分配空间
bucket_table[i]->key = 0;
bucket_table[i]->next = NULL;
}
for(int j=0;j<keys_size;j++)
{
Snode node_branch = (Snode)malloc(sizeof(Snode));
node_branch->key = keys[j];
node_branch->next = NULL;
int index = keys[j]/10;
Snode p = bucket_table[index];//p用来充当指向循环的变量。
if(p->key == 0){
bucket_table[index]->next = node_branch;
(bucket_table[index]->key)++;
}
//链表的插入形式,按照大小从后到大。
else{
while(p->next!=NULL && p->next->key <= node_branch->key){
p=p->next;
}
node_branch->next = p->next;
p->next = node_branch;
(bucket_table[j]->key)++;
}
}
//以此输出每个桶中的所有元素。
for(int i=0;i<bucket_size;i++){
for(Snode k = bucket_table[i]->next;k!=NULL;k = k->next){
printf(" %d ",k->key);
}
}
}
int main()
{
int keys[] = {49,26,53,47,89,31,72,11,33};
int keys_size = sizeof(keys)/sizeof(int);
int bucket_size = keys_size+2;
sort(keys,keys_size,bucket_size);
}
(7)基数排序
代码:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define LENGTH 10
int GetMaxWidth(int* arr,int len)//得到数据的最大宽度
{
int max=arr[0];
for(int i=0;i<len;++i)
{
if(max<arr[i])
{
max=arr[i];
}
}
int width=0;
while(max>0)
{
width++;
max/=10;
}
return width;
}
typedef struct Que //队列
{
int* data;
int head;
int tail;
}Que;
int GetNumOfData(int data,int width)
{
int num=data%10;//对10取余
while(width) //初始width==0,表示取个位的值,不进循环,直接返回num
{
data/=10;
width--;
num=data%10;
}
return num;
}
void RadixSort(int* arr,int len)
{
//获取最大数字的位数
int width=GetMaxWidth(arr,len);
Que que[10];
for(int i=0;i<10;++i) //初始化十个队列
{
que[i].data =(int*)malloc(sizeof(int)*len);
que[i].head =que[i].tail =0;
}
//i=0;个位 i=1;十位 i=2;百位 i=3;千位
for(int i=0;i<width;++i)
{
for(int j=0;j<len;++j)//进队列
{
int num=GetNumOfData(arr[j],i);
que[num].data [que[num].tail++]=arr[j];
}
int count=0;
for(int i=0;i<10;++i)//数据出队列进入arr中
{
while(que[i].head!=que[i].tail)//有数据
{
arr[count++]=que[i].data[que[i].head++];
}
que[i].head =que[i].tail=0;//队列初始化,为下一次放数据做准备
}
}
for(int i=0;i<10;++i)
{
free(que[i].data);
}
}
void ShowData(int* arr)
{
for(int i=0;i<LENGTH;++i)
{
printf("%d ",arr[i]);
}
printf("\n");
}
int main()
{
int arr[LENGTH]={};
srand((unsigned int)time(NULL));
for(int i=0;i<LENGTH;i++)
{
arr[i]=rand()%10000;//10000以内的随机数
}
ShowData(arr);
RadixSort(arr,LENGTH);//基数排序
ShowData(arr);
return 0;
}
(8)归并排序
代码:
#include<stdio.h>
#include<stdlib.h>
void Merge(int arr[], int tmp[], int start,int mid, int end)//合并小组并排序
{
int i = start;//i标识//左小组的第一个元素位置
int j = mid + 1;//j标识//右小组的第一个元素位置
int k = start;//tmp当前小组存放的起始位置
while (i < mid + 1 && j < end + 1)//左小组越界或右小组越界才能退出
{
if (arr[i] <= arr[j])
{
tmp[k++] = arr[i++];
}
else
{
tmp[k++] = arr[j++];
}
}
while (j < end + 1)//如果右边小组没有越界
{
tmp[k++] = arr[j++];
}
while (i < mid + 1)//如果左边小组没有越界
{
tmp[k++] = arr[i++];
}//哦哦就是补齐了,把数组放到新的那个临时数组中去了
for (i = start; i <= end; i++)
{
arr[i] = tmp[i];
}//至此,原来的数组已经排序完毕
}
void MergeS(int arr[], int tmp[], int start, int end)//划分小组,现在没有end.
{
if (start < end)
{
int mid = (start+end)/2;
MergeS(arr, tmp, start, mid);
MergeS(arr, tmp, mid + 1, end);//自我递归调用
Merge(arr, tmp, start, mid, end);//现在就全部排号
}
}//就是递归调用呗
void MergeSort(int arr[], int len)
{
int *tmp = (int *)malloc(sizeof(int)*len);//开了一个排序后结果保存的临时数组
MergeS(arr, tmp, 0, len - 1);//嵌套调用
free(tmp);
}
int main()
{
int arr[] = { 12, 3, 21, 32, 1, 34, 12, 35, 34 };//举例子
//int s,arr[100];
//scanf("%d",&s);
//for(int i=0;i<s;i++)
//{
// scanf("%d ",&arr[i]);
//}
int len = sizeof(arr) / sizeof(arr[0]);
MergeSort(arr, len);
for (int i = 0; i < len; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
(9)快速排序
代码:
#include <stdio.h>
#define SIZE 6
//快速排序
void quick_sort(int num[], int low, int high )
{
int i,j,temp;
int tmp;
i = low;
j = high;
tmp = num[low]; //任命为中间分界线,左边比他小,右边比他大,通常第一个元素是基准数
if(i > j) //如果下标i大于下标j,函数结束运行
{
return;
}
while(i != j)
{
while(num[j] >= tmp && j > i)
{
j--;
}
while(num[i] <= tmp && j > i)
{
i++;
}
if(j > i)
{
temp = num[j];
num[j] = num[i];
num[i] = temp;
}
}
num[low] = num[i];
num[i] = tmp;
quick_sort(num,low,i-1);
quick_sort(num,i+1,high);
}
int main(int argc , char **argv)
{
//创建一个数组
int num[SIZE] ={0};
int i;
//输入数字
for(i =0; i < SIZE; i++)
{
scanf("%d",&num[i]);
}
quick_sort(num, 0, SIZE-1);
for(i = 0; i < SIZE; i++)
{
printf(" %d ", num[i]);
}
return 0;
}
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了冒泡排序与选择排序的比较(C语言)。