排序算法(2)---选择排序

 

    这里先介绍简单选择排序,然后在介绍堆排序,(堆排序是选择排序的一种)

选择排序

 

 

    定义:

     选择排序(Selection Sort)是一种简单直观的排序算法。它是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。选择排序是不稳定的排序方法(比如序列【5,5,3】第一次就将第一个【5】与【3】交换,导致第一个5挪到第二个5后面)。

    优化:

    在选择排序每次遍历数组中,选择最大数与最小数然后在进行交换。

 图解:

  

    代码:

void SelectSort(int* a,size_t n)
{
	assert(a);
	size_t begin = 0;
	size_t end = n-1;

	while(begin < end)
	{
		size_t min = begin, max = end;
		for(size_t i=begin; i<=end; i++)
		{
			//选最大值、最小值的下标
			if(a[i] < a[min])
			{
				min = i;
			}

			if(a[i] > a[max])
			{
				max = i;
			}
		}
		//交换 
		if(max == begin) //(当max==begin时,应进行特殊处理)
		{
			max = min;
		}
		swap(a[begin],a[min]);
		swap(a[end],a[max]);

		++begin;
		--end;
	}
}

 

 

    时间复杂度:O(n^2)

堆排序

 

 

    定义:   

    堆排序(HeapSort)是指利用堆这种数据结构所设计的一种排序算法,它是选择排序的一种,可以利用数组的快速定位指定索引的元素。

 大堆排序的基本思想:

1.先将数据建成一个大堆。

2.再将对顶元素与最后一个元素进行交换,由于交换后新的堆可能违反堆的性质,故应将堆进行调整。

 

大根堆排序算法的基本操作:

1、建堆  建堆是不断调整堆的过程,从len/2处开始调整,一直到第一个节点。

2.调整堆   利用的思想是比较结点i和它的孩子结点left、right,选出三者最大者,如果最大(小)值不是节点i而是它的一个孩子结点,则交换后会影响这条路径上的其他节点,所以应继续往下调整,直到叶子结点。

3、堆排序:首先是根据元素构建堆,然后将堆的根节点与最后的结点进行交换,将前面len-1个结点继续进行堆调整,在交换根结点。

图解:

        

升序建大堆小堆问题分析:

 

 

            

       时间复杂度:  

       因为建堆的时间复杂度为O(n),调整堆的时间复杂度是O(lgN),调用了n-1次,所以堆排序的时间复杂度为O(nlgN)

 

    代码:

//堆排序(时间复杂度为O(nlogN))
void AdjustDown(int* a, size_t n, int root) //向下调整算法
{
	int parent = root;
	int child = parent*2+1;
	while(child < n)
	{
		if(child+1<n && a[child] < a[child+1]) //当存在左孩子时,进行判断   
		{
			++child;
		}

		if(a[child] > a[parent])
		{
			swap(a[parent],a[child]);
			parent = child;
			child = parent*2;
		}
		else
		{
			break;
		}
	}
}

void HeapSort(int *a, size_t n)
{
	assert(a);

	//建大堆(第一个元素为最大值)
	for(int i=(n-1-1)/2; i>=0; --i)
	{
		AdjustDown(a,n,i); 
	}
	//排序(将第一个元素与最后一个元素进行交换,再进行向下调整算法)
	int len = n-1;
	while(len > 0)
	{
		swap(a[0],a[len]);
		AdjustDown(a,len--,0);
	/*	len--;*/
	}
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值