常用的排序算法——C语言

常见排序算法可以分为两大类:

  • 比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。
  • 非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。

稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。

不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。

时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。

空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。

  

直接插入排序

#include<stdio.h>
#define N 10
int main()
{
	int a[N] = { 3,2,8,5,4,7,6,9,1,10 };  //定义数组;
	printf("原始数据为:\n");
	for (int i = 0; i < N; i++)  //输出原始数据;
		printf("%d ", a[i]);
	printf("\n\n");
	//对数组a进行直接插入排序,n为数组的长度;
	//[0,end]有序,end+1位置的值插入[0,end],让[0,end+1]有序。
	for (int i = 0; i < N-1; i++)
	{
		int end = i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
			if (a[end] > tmp)
			{
				a[end + 1] = a[end];
				end--;
			}
			else
			{break;}
		}
		a[end + 1] = tmp;
	}
	printf("排序后数据为:\n");
	for (int i = 0; i < N; i++)  //输出排序后数据;
		printf("%d ", a[i]);
	return 0;
}

折半插入排序

//折半插入排序;
#include<stdio.h>
#define N 10
int main(void)
{
	int a[N] = { 3,2,8,5,4,7,6,9,1,10 };  //定义数组;
	printf("原始数据为:\n");
	for (int i = 0; i < N; i++)  //输出原始数据;
		printf("%d ", a[i]);
	printf("\n\n");
	//对数组a进行折半插入排序,n为数组的长度;
	{
		for (int i = 1; i < N; i++)
		{
			int x = a[i];   //将需要进行插入排序的元素赋值给x;
			int low = 0, high = i - 1;  //设置折半的头和尾;	
			while (low <= high)
			{
				int mid = (low + high) / 2;  //设置中间元素,与插入的元素进行比较;
				if (x < a[mid])   //比较;
					high = mid - 1;
				else
					low = mid + 1;
			}
			for (int j = i - 1; j >= low; j--)  //记录依次向后移;
				a[j + 1] = a[j];   //将当前这个值赋给这个元素的后一个元素;
			a[low] = x;   //插入记录;
		}
	}
	printf("使用插入排序后的数据为:\n");
	for (int i = 0; i < N; i++)
		printf("%d ", a[i]);
	printf("\n");
	return 0;
}

希尔排序

#include<stdio.h>
#define N 10
int main()
{
	int a[N] = { 3,2,8,5,4,7,6,9,1,10 };  //定义数组;
	printf("原始数据为:\n");
	for (int i = 0; i < N; i++)  //输出原始数据;
		printf("%d ", a[i]);
	printf("\n\n");
	//对数组a进行希尔排序,n为数组的长度;
	int gop = 5;
	while (gop > 1)
	{
		gop = gop - 2;	//printf("%d\n", gop);
		for (int i = 0; i < N - gop; i++)
		{
			int end = i;
			int tmp = a[end + gop];
			while (end >= 0)
			{
				if (a[end] > tmp)
				{
					a[end + gop] = a[end];
					end = end - gop;
				}
				else
				{
					break;
				}
			}
			a[end + gop] = tmp;
		}
	}
	printf("排序后数据为:\n");
	for (int i = 0; i < N; i++)  //输出排序后数据;
		printf("%d ", a[i]);
	return 0;
}

简单选择排序

#include<stdio.h>
#define N 10
void Swap(int* a, int* b) {     //定义了类型为int*的指针a,b,指针指向的类型为int
	int tmp = *a;     //将指针a所指向的地址中的内容赋值给tmp
	*a = *b;   //将指针b所指向的地址中的内容赋值给指针a所指向的地址中的内容
	b = tmp;
}
void SelectSort(int* a, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		for (int j = i + 1; j < n; j++)
		{
			if (a[i] > a[j])
			{
				int num = a[i];
				a[i] = a[j];
				a[j] = num;
			}
		}
	}
}
int main()
{
	int a[N] = { 3,2,8,5,4,7,6,9,1,10 };  //定义数组;
	printf("原始数据为:\n");
	for (int i = 0; i < N; i++)  //输出原始数据;
		printf("%d ", a[i]);
	printf("\n\n");
	SelectSort(a, sizeof(a)/sizeof(int));
	printf("排序后数据为:\n");
	for (int i = 0; i < N; i++)  //输出排序后数据;
		printf("%d ", a[i]);
	return 0;
}

堆排序

#include<stdio.h>、
#define N 10
//交换,传地址
void Swap(int* child, int* parent)
{
	int tmp = *child;
	*child = *parent;
	*parent = tmp;
}

//向下调整算法
//从根节点开始,如果是建立小堆选出左右孩子中小的那一个,跟父亲比较,如果比父亲小就交换
void AdjustDwon(int* a, int n, int root)//建小堆
{
	int parent = root;//父亲节点
	int child = parent * 2 + 1;//默认是左孩子
	while (child < n)//叶子节点下标不会超过数组总下标数n
	{
		//选出左右孩子中最小的那一个
		if (child + 1 < n && a[child + 1] < a[child])
		{
			child += 1;//用a[child]与父亲节点a[parent]比较
		}
		if (a[child] < a[parent])
		{
			//交换,传地址
			Swap(&a[child], &a[parent]);
			//交换后,将child,作为根节点继续向下调整,持续建堆
			parent = child;
			//新的左孩子
			child = parent * 2 + 1;
		}
		else
		{
			break;//如果不用交换,直接结束循环
		}
	}
}

//堆的建立
//大堆要求:树中所有的父亲都>=孩子,根是最大的
//小堆要求:书中所有的父亲都<=孩子,根是最小的
//建大堆排升序,建小堆排降序
//建堆的时间复杂度是O(N);
void HeapSort(int* a, int n)
{
	//找父亲节点
	for (int i = (n - 1 - 1) / 2; i >= 0; --i)
	{
		//向下调整算法
		AdjustDwon(a, n, i);
	}
	//大堆或小堆建立完毕,排序
	//用主根节点与最后一个节点交换位置
	int end = n - 1;
	while (end > 0)
	{
		//交换,传地址
		Swap(&a[0], &a[end]);
		//继续向下调整
		AdjustDwon(a, end, 0);
		--end;
	}
}

//选择排序—堆排序
int main()
{
	int a[N] = { 9,2,5,4,3,1,6,7,8,10 };
	//堆的建立
	HeapSort(a, sizeof(a) / sizeof(int));
	for (int i = 0; i < N; ++i)
	{
		printf("%d ", a[i]);
	}
	return 0;
}


/*void Printf(int* a, int n)
{
	for (int i = 0; i < n; ++i)
	{
		printf("%d ", a[i]);
	}
}*/

冒泡排序

#include<stdio.h>
#define N 10
int main()
{
	int a[N] = { 3,2,8,5,4,7,6,9,1,10 };  //定义数组;
	printf("原始数据为:\n");
	for (int i = 0; i < N; i++)  //输出原始数据;
		printf("%d ", a[i]);
	printf("\n\n");
		for (int i = 0; i < N; i++)//控制交换次数 
		{
			for (int j = 0; j < N - i - 1; j++)//向后冒泡 ,控制边界 
			{
				if (a[j] > a[j + 1])//如果前一个值大于后一个值,交换. 
				{
					int t = a[j];
					a[j] = a[j + 1];
					a[j + 1] = t;
				}
			}
		}
	printf("排序后数据为:\n");
	for (int i = 0; i < N; i++)  //输出排序后数据;
		printf("%d ", a[i]);
	return 0;
}

快速排序

#include<stdio.h>
#define N 10
void QuickSort(int* a, int low, int high)
{
    if (low < high)
    {
        int i = low;
        int j = high;
        int k = a[low];
        while (i < j)
        {
            while (i < j && a[j] >= k)   j--;     // 从右向左找第一个小于k的数
            if (i < j)                  a[i++] = a[j];
            while (i < j && a[i] < k)    i++;    // 从左向右找第一个大于等于k的数
            if (i < j)                  a[j--] = a[i]; 
        }
        a[i] = k;
        // 递归调用
        QuickSort(a, low, i - 1);     
        QuickSort(a, i + 1, high);    
    }
}
int main()
{
    int a[N] = { 3,2,8,5,4,7,6,9,1,10 };  //定义数组;
    printf("原始数据为:\n");
    for (int i = 0; i < N; i++)  //输出原始数据;
        printf("%d ", a[i]);
    printf("\n\n");

    QuickSort(a, 0, N - 1);

    printf("排序后数据为:\n");
    for (int i = 0; i < N; i++)  //输出排序后数据;
        printf("%d ", a[i]);
    return 0;
}

联系方式:

(qq):2965191336      邮件:2965191336@qq.com

 图片,代码来自于自创,网络与好友

文章存在借鉴,如有侵权请联系修改删除!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值