排序算法(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--;*/
	}
}

猜你喜欢

转载自blog.csdn.net/smile_zhangw/article/details/80369510