数据结构---排序

排序:
排序算法的稳定性
内部排序算法和外部排序算法
排序算法的实现原理,代码实现,稳定性,时间复杂度,空间复杂度,应用场景

插入排序:

时间复杂度:最优O(N)最差O(N^2);
插入排序有最优的场景:如果数据的序列与用户所需序列是接近相同,比如:用户要升序,序列就是一个升序序列—>O(N);
最差场景:用户需要升序,数据恰好是降序—>O(N^2);
稳定性:稳定;
代码实现:


void InsertSort(int* array, int size,Cmp cmp)
{
	int i = 1;
	for (i = 1; i < size; i++)
	{
		int end = i - 1;
		int key = array[i];
		while (end >= 0 && cmp(key,array[end]))
		{
			array[end + 1] = array[end];
			end--;
		}
		array[end + 1] = key;
	}
}

应用场景:数据有序或者接近有序(数据与用户所需顺序一致)&数据量比较少
问题:----------------------------------------------------------------
数据凌乱(随机)而且数据量较大—要求:利用插入排序的思想来进行排序;
**解决方法:**将用户所给场景向插入排序的场景进行转变;

  • 数据凌乱—>想办法让数据逐渐接近有序;(比较困难)
  • 数据量大—>想办法让数据量变小(简单)
    所以分组;
    分组方式:让数据按照一定间隔分组,间隔(gap)渐渐减少,直到gap = 1;该种分组方式是希尔想出来的—>希尔排序(shellsort);

希尔排序:

代码实现

void ShellSort(int* array,int size)
{
	int gap = size;
	while(gap > 1 )
	{
		//gap = gap/2;希尔给的
		//gap每次给个素数(质数)(7,5,3,1)
		gap = gap/3+1//kunth大量数据证明效率高
		for(int i = gap;i<size;i++)
		{
			int key = array[i];
			int end = i - gap;
			while(end >= 0 && key < array[end])
			{
				array[end+gap] = array[end];
				end -= gap;
			}
			array[end+gap] = key;
		}
		//gap--;
	}
}

gap 不同人有不同看法;
看排序算法是否稳定:排序算法原理在插入时候是否隔着区间(隔着元素)来进行插入;
排序算法原理在交换时候是否隔着区间(隔着元素)来进行插入;–>是则不稳定
空间复杂度:O(1);
空间复杂度:kunth方法:O(N^1.25 )~ O(1.6N^1.25 )
稳定性:不稳定;

选择排序

代码实现

void Swap(int* left, int* right)
{
	int tmp = *left;
	*left = *right;
	*right = tmp;
}

//选择排序
void SelectSort(int* array, int size, Cmp cmp)
{
	for (int i = 0; i < size - 1; i++)
	{
		int minPos = 0;
		for (int j = 1; j < size - i; j++)
		{
			if (cmp(array[j], array[minPos]))
				minPos = j;
		}
		if (minPos != size - i - 1)
		{
			Swap(&array[minPos], &array[size - i - 1]);
		}
	}
}

时间复杂度:O(N^2);
空间复杂度:O(1);
稳定性不稳定;
选择排序的缺陷:整个序列前面元素重复比较;
思考:怎么才能够不做重复的事情?

堆排序:

1.建堆:建大堆还是小堆
//1.建堆—> 升序–>大堆,降序–>小堆
//向下调整—>从倒数第一个非叶子节(size-2)/2[(最后一个节点的下标-1)/2]点开始到根节点
2.堆排序

void AdjustDown(int* array,int size,int parent)
{
	int child = 2*parent+1;
	while(child<size)
	{
	if(child+1<size&&array[child+1]>array[child])
		child++;
	if(array[parent]<array[child])
	{	 	  Swap(&array[parent],&array[child]);
		 parent = child;
		 child = 2*parent+1;
	}
	else
		break;
	}
} 
void HeapSort(int* array, int size)//堆排序
{
	//1.建堆--->  升序-->大堆,降序-->小堆
	//向下调整--->从倒数第一个非叶子节(size-2)/2[**(最后一个节点的下标-1)/2**]点开始到根节点
	for (int root = (size - 1 - 1) / 2; root >= 0; root--)
	{
		AdjustDown(array, size, root);
	}
	//2.排序---->利用堆删除的思想
	int end = size - 1;
	while (end > 0)
	{
		Swap(&array[0], &array[end]);
		AdjustDown(array, end, 0);
		end--;
	}
}

空间复杂度:O(1);
时间复杂度:O((3N/2)logN)–>O(NlogN)
向下调整–>O(logN);
**稳定性:**不稳定;

交换排序

冒泡排序
for()—>外层循环:控制冒泡趟数
for()—>内层循环:控制冒泡方式

 void BubbleSort(int* array, int size)//冒泡排序
{
	//控制冒泡的趟数
	for (int i = 0; i < size - 1; i++)//-1的目的是可以少冒一趟,因为最后一次冒泡区间只剩下一个元素;
	{
		//冒泡方式:将相邻元素比较-->不满足条件就交换
		/*
		//法一:
		//j:后一个元素的下标;
		for (int j = 1; j < size - i; j++)
		{
			if (array[j - 1] > array[j])
				Swap(&array[j - 1], &array[j]);
		}
		*/
		//法二:
		//j:前一个元素的下标;
		for(int j = 0;j<size-i-1;j++)
		{	
			if(array[j]	> array[j+1])
			  Swap(&array[j],&array[j+1]);
		}
	}
}

代码二

void BubbleSort2(int* array, int size)//冒泡排序//处理{0,1,2,3,5,4}这种
{
	//控制冒泡的趟数
	for (int i = 0; i < size - 1; i++)//-1的目的是可以少冒一趟,因为最后一次冒泡区间只剩下一个元素;
	{
		int flag = 1;
		//冒泡方式:将相邻元素比较-->不满足条件就交换
		for (int j = 1; j < size - i; j++)
		{
			if (array[j - 1] > array[j])
			{
				flag = 0;//如果flag被改为0则这趟冒泡时区间还无序;
				Swap(&array[j - 1], &array[j]);
			}
		}
		if (flag)
			break;
	}
}

时间复杂度:O(N^2);
空间复杂度:O(1);
稳定性:稳定;
快速排序
数据分割:hore提出快排思想的大佬
取区间最左侧或者最右侧的数据为基准值;
(用begin标记数组最前面的元素,end标记最后面的元素,begin从前往后移动,end从后往前移动,如果begin和end没遇到或者没有错过,begin找到一个比基准值大的就停止,end找到一个比基准值小的就停止,交换begin和end所指元素最后交换相遇位置的和最右侧的元素 );

//分割代码
//hoare:提出快排思想的大佬提出的
int partion(int* array, int left, int right)
{
	int begin = left;
	int end = right - 1;
	int key = array[end];//基准值
	while (begin < end)
	{
		//让begin从前往后找,找>基准值的元素,找到就停止
		while (begin<end && array[begin] <= key)
			begin++;
		
		
		//让end从后往前找,找<基准值的元素,找到就停止
		while (begin<end && array[end] >= key)
			end--;
		if(begin<end)
			Swap(&array[begin], &array[end]);
	}
	if(begin!=right-1)
		Swap(&array[begin], &array[right - 1]);
	
	return begin;
}
//排序代码
void QuickSort(int* array, int left, int right)//快速排序[left,right)
{
	if (right - left > 1)//元素个数>1
	{
		//partion函数将区间[left,right)用最右侧基准值划分为前面元素<基准值
		//后面元素大于基准值;
		int div = partion(array, left, right);
		//基准值的左侧[left,div)
		QuickSort(array, left, div);
		//基准值的右侧[div+1,right)
		QuickSort(array, div + 1, right);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值