堆排序算法实现

排序算法--堆排序(大根堆实现)

堆排序的平均时间复杂度 :O(N*logN)

空间复杂度:O(1)

堆排序算法的演示。首先,将元素进行重排,以匹配堆的条件。图中排序过程之前简单的绘出了堆树的结构。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define LEFT 2*nRootID+1
#define RIGHT 2*nRootID+2

//1.建初始堆
//	(1)从最后一个父亲节点开始
//	  1.1比较左右孩子大小
//	  1.2拿大的和父亲比较
//	     比父亲大:与父亲交换,被交换位置作为新的被调整节点,重复1.1和1.2
//		 比父亲小:结束,进行下一个父亲节点 的调整
//2.排序
//  2.1 拿堆顶与当前数组的最后位置值交换
//  2.2最后位置元素不参与运算
// 
//调整父亲节点
void Adjust(int a[],int nlen,int nRootID)
{
	while (1)
	{
		//两个孩子
		if(RIGHT<nlen)
		{
			//比较两个孩子大小,大的和父亲交换值
			if(a[LEFT]>a[RIGHT])
			{
				if(a[LEFT]>a[nRootID])
				{
					//和父亲节点值交换
					a[LEFT]^=a[nRootID];
					a[nRootID]^=a[LEFT];
					a[LEFT]^=a[nRootID];
					nRootID=LEFT;
					continue;
				}
				else
				{
					break;
				}
			}
			
			else
			{
				if(a[RIGHT]>a[nRootID]){
				a[RIGHT]^=a[nRootID];
				a[nRootID]^=a[RIGHT];
				a[RIGHT]^=a[nRootID];
				nRootID=RIGHT;
				continue;
				}
				else
				{
					break;
				}
			}
		}
		
		//一个孩子
		else if (LEFT<nlen)
		{
			if(a[LEFT]>a[nRootID])
			{
				//大的和父亲交换
				a[LEFT]^=a[nRootID];
				a[nRootID]^=a[LEFT];
				a[LEFT]^=a[nRootID];
				nRootID=LEFT;
				continue;
			}
			else
			{
				break;
			}
		}
		else
		{
			//没有孩子
			break;
		}
	}
}

void Adjust2(int a[],int nlen,int nRootID)
{
	int MAX;
	for(MAX=LEFT;MAX<nlen;MAX=LEFT)
	{
		//2个孩子
		if(RIGHT<nlen)
		{
			if(a[RIGHT]>a[LEFT])
			{
				MAX=RIGHT;
			}
		}

		//大的和父亲节点交换
		if(a[MAX]>a[nRootID])
		{
			a[MAX]^=a[nRootID];
			a[nRootID]^=a[MAX];
			a[MAX]^=a[nRootID];

			nRootID=MAX;
		}
		else
		{
			break;
		}
	}

}

void HeapSort(int a[],int nlen)
{
	int i;
	if(a==NULL ||nlen<=0) return ;
	//从最后一个父亲节点开始调整
	for(i=nlen/2-1;i>=0;i--)
	{
		//Adjust(a,nlen,i);

		Adjust2(a,nlen,i);
	}
	//排序

	for(i=nlen-1;i>0;i--)
	{
//Adjust(a,nlen,i);

		Adjust2(a,nlen,i);
	}
	//排序

	for(i=nlen-1;i>0;i--)
	{
//从最后一个父亲节点开始调整为大根堆

a[0]^=a[i];a[i]^=a[0];a[0]^=a[i];//重新调整堆顶

 
		//Adjust2(a,i,0);
		Adjust2(a,i,0);
	}
}


int main()
{
	int i;
	int a[]={5,3,2,1,4,6,8,9,7}; 
	int len=sizeof(a)/sizeof(a[0]);
	HeapSort(a,len);

	for(i=0;i<len;i++)
	{
		printf("%d ",a[i]);
	}
	system("pause");
	return 0; 
}//Adjust2(a,i,0);
		Adjust2(a,i,0);
	}
}


int main()
{
	int i;
	int a[]={5,3,2,1,4,6,8,9,7}; 
	int len=sizeof(a)/sizeof(a[0]);
	HeapSort(a,len);

	for(i=0;i<len;i++)
	{
		printf("%d ",a[i]);
	}
	system("pause");
	return 0; 
}

更新:C++11 实现堆排序

#include <iostream>
#include <vector>
using namespace std;


void adjust(vector<int>& nums, int len, int index)
{
    // 定义左右孩子
    int left = 2*index+1;
    int right = 2*index+2;

    int maxIndex = index;

    // 判断左右孩子和index和大小
    if(left < len && nums[left] > nums[maxIndex]) {
        // 交换
        // swap(nums[left], nums[maxIndex]);
        // 更新当前最大节点位置
        maxIndex = left;
    }

    if(right < len && nums[right] > nums[maxIndex]) {
        // swap(nums[right], nums[maxIndex]);
        maxIndex = right;
    }

    // 交换
    if(maxIndex != index) {
        swap(nums[maxIndex], nums[index]);
        adjust(nums, len, maxIndex);
    }
}

void HeapSort(vector<int>& nums, int len)
{
    if (nums.size() == 0 || len <= 1) return;

    // 构建一个大根堆 从最后一个非叶子节点开始向前构建
    // 数组从下标0开始,父亲节点坐标范围:i = 0-- len/2-1
    // 左孩子:2*i+1
    // 右孩子:2*i+2
    for(int i = len/2-1; i >=0; i--)
    {
        adjust(nums, len, i);
    }

    // 堆顶和最后一个元素交换,剩余堆调整
    for(int i = len - 1; i > 0; i--)
    {
        // 拿出堆顶和最后一个元素交换
        swap(nums[i], nums[0]);
        // 剩余数组继续调整堆结构
        adjust(nums, i, 0);
    }

}
int main()
{
    vector<int> a = {5,9,6,2,7,4,3};
    int len = a.size();
    HeapSort(a, len);

    for(int i = 0; i < len; i++){
        cout << a[i] << " ";
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值