冒泡排序、选择排序、直接插入排序、希尔排序、推排序、桶排序、基数排序、归并排序、快速排序的比较(C语言)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

题目:

目录

(1)冒泡排序

(2)选择排序

(3)直接插入排序

(4)希尔排序

  (5)推排序

(6)桶排序

(7)基数排序

(8)归并排序

(9)快速排序


(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语言)。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

酷酷滴Q

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值