数据结构--排序(冒泡)

本文详细介绍了三种基础但重要的算法:冒泡排序,二分查找和插入排序。冒泡排序通过相邻元素比较实现排序,最佳情况时间为O(n),最坏情况为O(n^2)。二分查找适用于有序序列,查找效率高,时间复杂度为O(log n)。插入排序则将待排序元素逐个插入已排序序列,稳定且时间复杂度为O(n^2)。这些算法对于理解排序和查找的基本原理至关重要。
摘要由CSDN通过智能技术生成

1.冒泡排序

1.冒泡排序的原理是:从左到右,相邻元素进行比较。每次比较一轮,就会找到序列中最大的一个或最小的一个。这个数就会从序列的最右边冒出来。

以从小到大排序为例,第一轮比较后,所有数中最大的那个数就会浮到最右边;第二轮比较后,所有数中第二大的那个数就会浮到倒数第二个位置……就这样一轮一轮地比较,最后实现从小到大排序。每次排序的元素都会减少,直到没有任何一队元素需要比较。
比较时,每轮中第 n 次比较是新序列中第 n 个元素和第 n+1 个元素的比较(假如 n 从 1 开始)
时间复杂度:
最好情况:是有序的,只需遍历一遍即可 O(n)
最坏情况:全部无序,每次都要交换 O(n*2)

#include<stdio.h>
#include<assert.h>

//冒泡排序 -->每次确定一个最大的
void BubbleSort(int *a, int n)
{
	assert(a);
	for (size_t i = 0; i < n - 1; i++)//比较n-1轮,最后一个不需要比较
	{
		int exchange = 0;//设置一个标志位
		for (size_t j = 0; j < n - 1 - i; j++)//每一轮比较n-1-i次,每一轮少比较1次
		{
			if (a[j]>a[j + 1])//从小到大排序
			{
				//swap(&a[j], &a[j + 1]);//交换
				size_t tmp = a[j];
				a[j] = a[j + 1];
				a[j + 1] = tmp;
				exchange = 1;
			}
		}
		if (exchange == 0)//若没有发生交换,则直接退出,优化
			break;
	}
}
int main()
{
	int  a[10] = { 5, 88, 23, 14 };
	BubbleSort(a, 4);
	return 0;
}

2.二分查找(折半查找)

一个有序序列的高效查找算法
实现思路:

int mid = begin + ((end - begin) >> 1)
这样是防止溢出的写法(记住就好)

int BinarySearch(int *a, int n, int x)
{
	assert(a);
	int begin = 0;
	int end = n - 1;
	while (begin <= end)//两个相等时,判断的是最后一位
	{
		int mid = begin + ((end - begin) >> 1); 
		if (a[mid] < x)
		{
			begin = mid + 1;
		}
		else if (a[mid]>x)
		{
			end = mid - 1;
		}
		else
			return mid;
	}
	return -1;//查找失败
}
int main()
{	
	int  a[100] = { 1,3,4,6,7,8,10,13,14 };
	BinarySearch(a, 9, 4);
	printf("%d", BinarySearch(a, 9, 4));
}
	

3.插入排序

**思想:**直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。
实际中我们玩扑克牌时,就用了插入排序的思想。
在这里插入图片描述

当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,此时用array[i]的排序码与array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将array[i]插入,原来位置上的元素顺序后移。
直接插入排序的特性总结:

  1. 元素集合越接近有序,直接插入排序算法的时间效率越高
  2. 时间复杂度:O(N^2)
  3. 空间复杂度:O(1),它是一种稳定的排序算法
  4. 稳定性:稳定

有序位置的最后一个位置向前遍历,找到第一个小于待插数据的位置,然后这个数据放入已经找到位置的下一个位置

代码实现:

void InsertSort(int* a, int lenth)
{
	int i, j, z, index;

	for (j = 1; j < lenth; j++)//待插入数据 从1开始 首元素为初始有序数列
	{
		for (i = j - 1; i >= 0; i--)//已排序数据
		{
			if (a[j] > a[i])//在已排序列中找到位置
			{
				break;
			}
		}
		index = a[j];//将待插入数据拷贝出来等待 下面数据后移时会覆盖该数据
		if (i != j - 1)//不是有序数据末尾
		{
			for (z = j; z > i; z--)//数据后移,留出待插空位
			{
				a[z] = a[z - 1];
			}
			a[i + 1] = index;
		}
	}
}
void InsertSort(int* a, int lenth)
{
	//假设第一个数据有序
	//要拍的[1,n)
	for (int i = 1; i < lenth; ++i)//代排的
	{
		int end = i - 1;
		int data = a[i];
		while (end >= 0 && a[end] >= data)
		{
			a[end + 1] = a[end];//大的向后移动
			--end;
		}//end=-1时退出
		a[end + 1] = data;//end位置是比待排数据要小的,
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值