C语言数据结构之选择排序

1,直接选择排序(效率很低)

(1)时间复杂度O(N*N)

(2)代码:

void SelectSort(int arr[],int n)
{
	//定义一个begin和end的下标,begin位置放较小的数,end位置放较大的数
	//此算法可以一次选两个数,分别从数组的两头开始选择
	int begin = 0;
	int end = n - 1;
	while (begin < end)
	{
		int mini = begin;
		int maxi = begin;
		//每次从begin到end开始选择,用mini和maxi两个下标来记录每次遍历的最大值和最小值
		for (int i = begin; i <= end; i++)
		{
			if (arr[mini] > arr[i])
			{
				mini = i;
			}
			if (arr[maxi] < arr[i])
			{
				maxi = i;
			}
		}
		//交换两个数所在的位置,让小数在数组左边,大数在数组右边
		Swap(&arr[begin], &arr[mini]);
		//特殊情况:当begin=maxi时,经过上一次的交换,maxi所指向的已经不是最大值了,而mini所指向的是最大值,所以让maxi=mini
		//比如数组:9 3 5 2 7 8 6 -1 9 4
		if (begin == maxi)
		{
			maxi = mini;
		}
		Swap(&arr[end], &arr[maxi]);
		begin++;
		end--;
	}
}
void TestSelectSort()
{
	int arr[] = { 4,3,5,6,7,9,8,1,0,2 };
	SelectSort(arr, sizeof(arr) / sizeof(arr[0]));
	ArrPrint(arr, sizeof(arr) / sizeof(arr[0]));
}

2,堆排序(时间复杂度为O(N*logN,以二为底))

(1)前提知识:

堆的逻辑结构是一个完全二叉树,物理结构还是一个数组

堆的两个特性:结构性,用数组表示的完全二叉树;有序性,父亲节点是左子树右子树中的最大值或最小值。

大堆要求:树中所有父亲节点都大于等于孩子节点

小堆要求:树中所有父亲节点都小于等于孩子节点

通过下标父亲与孩子节点的关系:

leftchild=parent*2+1

rightchild=parent*2+2

parent=(child-1)/2

向下调整算法:(前提是左子树右子树都是大堆或者小堆)

从根节点开始,选出左右孩子中较小(大)的那个,去跟父亲节点进行比较,如果比父亲小(大)就交换,然后再往下调,知道叶子结点就结束。这样就可以保证父亲节点是最值。

(2)代码:

void ArrPrint(int a[], int n)
{
	int i = 0;
	for (i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
}
void Swap(int* p1, int* p2)
{
	int temp = *p1;
	*p1 = *p2;
	*p2 = temp;
}
//向下调整算法,前提是左右子树都是小堆或者是大堆,目的是确保根节点是最小的
void AdjustDown(int arr[], int n, int root)
{
	int parent = root;
	int child = parent * 2 + 1;
	while (child < n)
	{
		//选出最小(大)的孩子(child+1<n是为了确保只有一个节点的时候不报错)
		if (child+1<n&&arr[child + 1] > arr[child])
		{
			child++;
		}
		//跟父亲进行比较
		if (arr[child] > arr[parent])
		{
			Swap(&arr[parent],&arr[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}
void HeapSort(int arr[], int n)
{
	//建堆的时间复杂度为0(n)
	//把数组建成堆,可以一个一个树进行调整,从最后一个非叶子节点开始调(实际上就是最后一颗树)
	//最后一个非叶子结点其实就是最后一个节点的父亲
	for (int i = (n - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(arr, n, i);
	}
	//排升序,要建大堆
	int end = n - 1;
	while (end > 0)
	{
		Swap(&arr[0], &arr[end]);
		AdjustDown(arr, end, 0);
		end--;
	}
}
void TestHeapSort()
{
	//堆排序的时间复杂度为N*LogN(以二为底)
	int arr[] = { 4,3,5,6,7,9,8,1,0,2 };
	HeapSort(arr, sizeof(arr) / sizeof(arr[0]));
	ArrPrint(arr, sizeof(arr) / sizeof(arr[0]));
}

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值