【数据结构和算法】排序算法之二:选择排序和堆排序

一  选择排序

(1)思想

假设有十张扑克牌放在桌上,我们需要按从小到大的顺序拿到手上,每次只能选择一张牌拿到手上,那么每一次我们都必须从桌上的扑克牌中选择最小的牌拿起来,一次循环十次,这样就将扑克牌按从小到的顺序拿到手上了。这就是选择排序。

(2)实现

//选择排序
//输入:待排序数组(A)和数组个数(n)
//输出:按从小到大排序的数组(A)
void Select_sort(SortArray *A,int n)
{
	int i,j,min;
	int temp;
	for (i = 0 ; i < n -1 ; i++)
	{
		min = i;
		for (j = i+1 ; j < n ; j++)
		{
			if ((*A)[min] > (*A)[j])
			{
				min = j;
			}
		}
		if (i != min)
		{
			temp = (*A)[i];
			(*A)[i] = (*A)[min];
			(*A)[min] = temp;
		}
	}
}
选择排序是一种简单直观的排序算法,但它并不稳定。其不稳定性体现在:如果一个元素比当前元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后的稳定性就被破坏了(百度百科解释),照我的理解应该是,如果按序列(3,5,3,2,1)来说,在当前序列中前一个3的优先级大于后面的3,但是第一次排序就将第一个3换到了后面,因此该算法不稳定。

选择排序优于冒泡排序,其比较次数减少了,但是其算法复杂度依然是O(N2).

二  堆排序算法

(1)  思想

在选择排序中,我们每次从待排序数组中选择最小的数是根据遍历数组比较得来的,这种方法的效率低。

在堆排序中,利用最小/最大堆来获取待排序数组的最小/最大值。

(2)  实现

在堆排序中,最重要的是构建最大堆。

//构建 最大堆
void Heap_adjust(SortArray *A , int s , int n)
{
	int temp , i ;
	temp = (*A)[s];
	for (i = 2*s+1 ; i <= n ; i = 2*i +1)
	{
		if (i < n-1 && (*A)[i] < (*A)[i+1])
		{
			++i;
		}
		if (temp > (*A)[i])
		{
			break;
		}
		(*A)[s] = (*A)[i];
		s=i;
	}
	(*A)[s] = temp;
}
构建最大堆的时间复杂度0(n)

堆排序算法

void Heap_sort(SortArray *A,int n)
{
	int i;
	for (i = n/2-1 ; i >=0; i--)
	{
		Heap_adjust(A,i,n-1);
	}

	for (i = 0 ; i <n ; i ++)
	{
		cout<<(*A)[i]<<endl;
	}
	for ( i = n -1 ; i >=0 ; i--)
	{
		int temp = (*A)[0];
		(*A)[0] = (*A)[i];
		(*A)[i] = temp;
		Heap_adjust(A , 0 , i-1);
	}
}
在堆排序中,需要反复重建最大堆,其时间复杂度为O(nlogn)

所以,总时间复杂度为O(nlogn),其优于冒泡排序和选择排序等。

附:主程序代码

#include <stdio.h>
#include "stdafx.h"
#include <iostream> 
using namespace std;

#define MAX 100
typedef int SortArray[MAX];

int _tmain(int argc, _TCHAR* argv[])
{
	int n ;
	SortArray A;
	cout<<"/**选择排序和堆排序**/\n"
		<<"请输入数组个数"<<endl;
	cin>>n;
	cout<<"请输入待排序数组"<<endl;
	for (int i = 0 ; i < n ; i++)
	{
		cin>>A[i];
	}
	cout<<"正在排序请稍后....."<<endl;
	//Bubble_sort(&A,n);
	//Select_sort(&A,n);
	//Insert_sort(&A,n);
	//Shell_sort(&A,n);
	Heap_sort(&A,n);
	cout<<"排序结果如下....."<<endl;
	for (int i = 0 ; i < n ; i++)
	{
		cout<<A[i]<<endl;
	}
	system("pause");
	return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值