数据结构---排序算法(1)

排序:

定义:

排序指的是将一组无序的数据元素(如数字、字符串等)按照特定的规则(如升序、降序)重新排列成有序序列的过程。

排序算法是一种能将一组数据按照预设顺序(通常为升序或降序)进行排列的算法。它通过一系列指令或步骤,对数据元素进行比较和移动,最终使整个数据集呈现出有序的状态。

排序算法衡量标准

1、时间复杂度:

        指算法执行所需的时间与数据规模之间的关系,用于衡量算法的效率。通常关注最坏情况、平均情况和最好情况下的时间复杂度。

2、空间复杂度:

        指算法执行过程中所需的额外存储空间与数据规模之间的关系。

3、稳定性:

        若两个相等的元素在排序前后的相对位置保持不变,则该排序算法是稳定的;否则为不稳定。

4、适用性

        包括算法对数据规模的适应能力(如小规模数据适合插入排序,大规模数据适合快速排序)、对数据初始状态的敏感程度(如已接近有序的数据,插入排序效率更高)等。

5、实现复杂度

        指算法的代码实现难度,如冒泡排序实现简单,而堆排序实现相对复杂。

直接插入排序:

例如:

(1)判断arr是否为空

(2)从i=1位置开始,找到每个数据的位置(小数向左走,大数向右走)

例如:将arr[1]保存起来,和arr[0]比较,3大于2,3向右走,前面没有数了,2放入arr[0]

(3)i++到i=2,将arr[2]保存起来找到每个数据的位置,重复以上(2)(3)步骤直至i=len-1

void InsertSort(int* arr, int len)
{
	if (arr == NULL || len == 0) return;
	for (int i = 1; i < len; i++)
	{
		int temp = arr[i];
		int j = i-1;
		for (j; j >= 0; j--)
		{
			if (arr[j] > temp)
			{
				arr[j + 1] = arr[j];
			}
			else
				break;
		}
		arr[j + 1] = temp;
	}
}
1、时间复杂度为O(n2 )
2、空间复杂度为O(1)
3、稳定性:稳定

冒泡排序:

例如:

(1)判断arr是否为空

(2)从第一个数据开始和相邻数据比较,大数向右走,小数向左走(arr[j]>arr[j+1]所以交换arr[j]和arr[j+1])第一轮做到将最大数移动到最右

,重复以上步骤

循环以上步骤至i=len-1

void BubbleSort(int* arr, int len)
{
	if (arr == NULL || len == 0) return;
	for (int i = 0; i < len; i++)
	{
		for (int j = 0; j < len-1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
				Swap(&arr[j], &arr[j + 1]);
		}
	}
}

void Swap(int* pa, int* pb)
{
	int i = *pa;
	*pa = *pb;
	*pb = i;
}
1、时间复杂度为O(n2 )
2、空间复杂度为O(1)
3、稳定性:稳定

选择排序:

例如:

(1)判断arr是否为空

(2)先找出数组中最小的数,保存其下标为min

(3)比较下标i保存的数及min保存的数,将最小的数移动到数组最前方

重复以上步骤直到i=len-1

void SelectSort(int* arr, int len)
{
	if (arr == NULL || len == 0) return;
	for (int i = 0; i < len; i++)
	{
		int min = i;
		for (int j = i + 1; j < len; j++)
		{
			if (arr[j] < arr[min])
				min = j;
		}
		if (arr[i] > arr[min])
		{
			Swap(&arr[i], &arr[min]);
		}
	}
}
void Swap(int* pa, int* pb)
{
	int i = *pa;
	*pa = *pb;
	*pb = i;
}
1、时间复杂度:O(n2 )
2、空间复杂度:O(1)
3、稳定性:不稳定

快速排序:

通过一趟排序将待排序序列分割成两部分,其中一部分序列的关键字均比另一部分序列的关键字小,则可分别对这两部分子序列继续进行排序,以达到整个序列完全有序的目的。
1、每一趟的子序列的形成是采用从两头向中间交替式逼近法
2、由于每趟中对各子序列的操作都相似,大部分情况下采用递归算法
排序步骤:
(1)让leftright分别指向序列的最左端和最右端
(2)第一个值看做基准值放入tmp中,然后以right--的方式从右向左找一个比基准值小的值,放到左边空位,然后再以left++的方式从左向右找一个比基准值大的值,放到右边空位,循环往复,让leftright向中间逼近,直到leftright相遇
(3)将刚才临时保存在tmp中的基准值放回来,把左右两边数据分别重复以上步骤直至left=right,每组里面只有一个数据。
int partition(int* arr, int left, int right)
{
	int tmp = arr[left];
	while (left < right)
	{
		while (left<right&&arr[right] > tmp)
			right--;
		arr[left] = arr[right];
		while (left < right&&arr[left] <= tmp)
			left++;
		arr[right] = arr[left];
	}
	arr[left] = tmp;
	return left;
}
void Quick(int* arr, int left,int right)
{
	assert(arr != NULL);
	int index = partition(arr, left,right);
	if (index - 2 >= left)
	{
		Quick(arr, left, index - 1);
	}
	if (index + 2 <= right)
	{
		Quick(arr, index + 1, right);
	}
}
void QuickSort(int* arr, int len)
{
	assert(arr!= NULL && len>=1);
	if (len == 1)return;
	Quick(arr, 0, len - 1);
}
1、时间复杂度:O(nlog2n)
2、空间复杂度:如果快速排序采用递归写法,需要有一个栈用来存放每层递归调用时的参数(新的 left和right),且最大递归调用层数与递归树的深度一致,因此,空间开销为O(log2n)
3、稳定性:不稳定

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值