简单选择排序与堆排序

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">选择排序的基本运算都是在n个元素组成的序列中,选择一个关键字最大或最小的元素输出,然后再从剩余的n-1个元素中选择一个关键字最大或最小的元素输出,以此类推,直到排序结束。</span>
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">以递增排序为例,<span style="color:#ff0000;">简单选择排序</span>过程如下:1第一次在数组中查找最小值a[i],然后将a[i]和a[0]交换位置。</span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">	</span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">2从a[1]开始,同样从a[1]开始往后找到最小值a[j],然后与a[1]交换位置,依次类推。</span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">废话不多说,直接贴代码</span>
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">
</span>
//**************5简单选择排序************************
//比冒泡法交换的次数少,比较多,交换少
void SelectSort(int a[],int len)
{
	int i,j,min,temp;
	for(i=0;i<len-1;i++)
	{
		min=i;
		for(j=i+1;j<len;j++)
			if(a[j]<a[min])
				min=j;
		temp=a[i];
		a[i]=a[min];
		a[min]=temp;
	}
}

简单选择排序    时间复杂度O(n^2)

稳定性分析:选择排序是给每个位置选择当前元素最小(或最大)的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个 元素不用选择了,因为只剩下它一个最大的元素了。那么,在一趟选择,如果当前元素比一个元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么
交换后稳定性就被破坏了。比较拗口,举个例子,序列5 8 5 2 9, 我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序是一个不稳定的排序算法。

简单选择排序的时间主要浪费在对于n个元素(乱序)如何----在小于O(n)时间内查找最大值或最小值

改进:堆排序

堆是一棵完全二叉树,其中任一非叶子节点的关键字均大于(或小于)等于其孩子节点的关键字。分为最大堆和最小堆

用最大堆进行升序排序:先构造初始最大堆,由于最大堆的第一个关键字就是最大值,直接将第一个关键字和最后一个关键字交换(是不是和简单选择排序很相似),然后再调整其余关键字,使其重新构成最大堆,然后再将第一个关键字与当前最大堆的最后一个关键字交换,依次类推,直到排序完成。

简而言之就是: 构造初始堆---->取堆顶------>调整剩余堆------>取剩余堆顶------->.........-------->空堆end

构造初始堆的过程描述如下:

废话不多说,直接上代码:

//*****************6堆排序*******************************
//升序排序构造大顶堆,每次把最大元素(根)放在数组最后一个位置
//对于剩余元素重新构造二叉堆-----以数组形式存储堆 (完全二叉树)
void HeapAdjust(int a[], int i, int size)
{
	//调整堆(大小为size--a[0~size])的第i个节点使之为大顶堆  size=len-1;节点编号0,1,...size.
		int lchild = 2*i+1;//i的左孩子节点序号
		int rchild = 2*i+2;//i的右孩子节点序号
		int max=i;
		int temp;

		if(i<=size/2)//如果i是叶节点就不用进行调整
		{
			if(lchild<=size && a[lchild]>a[max])
				max=lchild;
			if(rchild<=size && a[rchild]>a[max])
				max=rchild;
			if(max!=i)
			{
				temp=a[i];
				a[i]=a[max];
				a[max]=temp;
				//避免调整之后以man为父节点的子树不是大顶堆
				HeapAdjust(a,max,size);
			}
		}
}

void HeapSort(int a[],int size)
{
	//HeapSort(a,9);size=n-1;不是元素个数
	int i,temp;

	for(i=size/2;i>=0;i--)//建立初始堆 非叶子节点最大序号值为size/2
	   HeapAdjust(a,i,size);
	for(i=size;i>=0;i--)
	{
		temp=a[0];   //交换堆顶和最后一个元素
		a[0]=a[i];
		a[i]=temp;
		//BuildHeap(a[],i-1);//将余下元素重新建立为大顶堆
		HeapAdjust(a,0,i-1);//重新调整堆顶节点成为大顶堆
	}
}

由于堆是完全二叉树,其实还是用数组来描述堆。。。。。

下面对代码进行解释:

HeapSort第一个for循环就是建立堆的过程,从第一个非叶子节点开始进行调整堆(HeapAdjust)最后一个个非叶子节点可能是size/2,可有可能是size/2-1,至于为什么从编号为size/2开始,是为了保证最大可能性,进一步的确定是不是叶子节点可在HeapSort中的if(lchild<=size)等中进行判断。

HeapSort第二个for循环就是取堆顶,调整堆的过程。

下面分析时间复杂度(参考算法导论)

分析调整堆的时间复杂度

重调堆,时间复杂度为T(lgn)

堆排序的时间复杂度T(nlgn)  无论最好最坏都是一样的

时间: 2024-10-08 15:06:38

简单选择排序与堆排序的相关文章

算法之简单选择排序和堆排序

3. 选择排序-简单选择排序(Simple Selection Sort) 基本思想: 在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换:然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后一个数)比较为止. 简单选择排序的示例: 操作方法: 第一趟,从n 个记录中找出关键码最小的记录与第一个记录交换: 第二趟,从第二个记录开始的n-1 个记录中再选出关键码最小的记录与第二个记录交换: 以此类推.....

算法导论 第6章 堆排序(简单选择排序、堆排序)

堆数据结构实际上是一种数组对象,是以数组的形式存储的,可是它能够被视为一颗全然二叉树,因此又叫二叉堆.堆分为下面两种类型: 大顶堆:父结点的值不小于其子结点的值,堆顶元素最大 小顶堆:父结点的值不大于其子结点的值,堆顶元素最小 堆排序的时间复杂度跟合并排序一样,都是O(nlgn),可是合并排序不是原地排序(原地排序:在排序过程中,仅仅有常数个元素是保存在数组以外的空间),合并排序的全部元素都被复制到另外的数组空间中去,而堆排序是一个原地排序算法. 1.在堆排序中,我们通常使用大顶堆来实现,因为堆

Java中的基础排序算法(二):简单选择排序、堆排序

参考文章:https://mp.weixin.qq.com/s/VjqZNPg6dAEReAzqZcb_yw 原文链接:www.jianshu.com/p/5e171281a387 原文地址:https://www.cnblogs.com/lotuses/p/11640671.html

七大内部排序算法总结(插入排序、希尔排序、冒泡排序、简单选择排序、快速排序、归并排序、堆排序)

 写在前面: 排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的任意序列,重新排列成一个按关键字有序的序列.因此排序掌握各种排序算法非常重要.对下面介绍的各个排序,我们假定所有排序的关键字都是整数.对传入函数的参数默认是已经检查好了的.只是简单的描述各个算法并给出了具体实现代码,并未做其他深究探讨. 基础知识: 由于待排序的记录数量不同,使得排序过程中设计的存储器不同,可将排序方法分为两大类:一类是内部排序,指的是待排序记录存放在计算机随机存储器中进行的排序过程.另一类是外部排序,

排序算法2--简单选择排序、堆排序

一.简单选择排序和堆排序都属于选择排序 选择排序的思想是:每一趟从待排序的记录中选出关键字最小的记录,按顺序放在以排序的记录序列的后面,知道全部拍完为止. 二.简单选择排序(直接选择排序) 1.简单选择排序法是每次循环找出最值,循环结束后将最值调整到合适位置,交换的次数少. 每次找出当前无序队列中的最小的元素与第一个交换位置,再选择第二小的与第二个交换位置 原始队列:   3 5 6 2 4 1(最小元素1与3交换) 第一步: 1 5 6 2 4 3 (当前最小元素2与5交换) 第二步: 1 2

选择排序---简单选择排序 堆排序

一.简单选择排序 对于n个数要进行n次排序,第一次,将最小的数放在第一个.第二次,将第二小的树,放在第二个.... 每次都和后面的数做比较,如果是从小到大的排序,当当前的数字比后面的大时,要进行交换. #include <stdio.h> void chosesort(int a[],int length) { int i,j,temp; for(i=0;i<length;i++) for(j=i+1;j<length;j++) { if(a[i]>a[j]) { temp

4.3_8种常用排序算法3(选择排序:简单选择排序+堆排序)

[简单选择排序] package com.sort.demo3; import java.util.Arrays; /** * 简单选择排序 */ public class SelectSort { public static void main(String[] args) { int[] arr = new int[]{1,4,5,7,3,9,8,0,2,6}; System.out.println(Arrays.toString(arr)); selectSort(arr); System

选择排序:堆排序

堆排序(Heap Sort):使用堆这种数据结构来实现排序. 先看下堆的定义: 最小堆(Min-Heap)是关键码序列{k0,k1,-,kn-1},它具有如下特性: ki<=k2i+1, ki<=k2i+2(i=0,1,-) 简单讲:孩子的关键码值大于双亲的. 同理可得,最大堆(Max-Heap)的定义: ki>=k2i+1, ki>=k2i+2(i=0,1,-) 同样的:对于最大堆,双亲的关键码值大于两个孩子的(如果有孩子). 堆的特点: 堆是一种树形结构,而且是一种特殊的完全二

排序算法七:选择排序之堆排序

排序算法七:选择排序之堆排序 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 引言 在我的博文<"主宰世界"的10种算法短评>中给出的首个算法就是高效的排序算法.本文将对排序算法做一个全面的梳理,从最简单的"冒泡"到高效的堆排序等. 上博文讲述了选择排序中的简单排序算法,本文介绍的堆排序是树性选择排序,采用堆这个数据结构来辅助排序. 排序相关的的基本概念 排序:将一组杂乱无章的数据按一定的规律顺次排列起来. 数据