堆的TopK问题,优先级序列,堆排序d

堆的概念:

    如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元 素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:   Ki <= K2*i+1 且 Ki<= K2*i+2 (Ki >= K2*i+1 且 Ki >= K2*i+2) i = 0,1,2…,则称为小堆(或大堆)。

    小堆(大堆)中:任一结点的关键码均小于(大于)等于它的左右孩子的关键 码,位于堆顶结点的关键码最小(最大),从根节点到每个结点的路径上数 组元素组成的序列都是递增(递减)的堆存储在下标为0开始的数组中,因此在堆中给定下标为i的结点时

        如果i=0,结点i是根节点,没有双亲节点;否则结点i的双亲结点为 结点(i-1)/2 
        如果2 * i + 1 <= n - 1,则结点i的左孩子为结点2 * i + 1,否则结 点i无左孩子 

        如果2 * i + 2 <= n - 1,则结点i的右孩子为结点2 * i + 2,否则结 点i无右孩子


堆的创建:

void MakeHeap(Datatype *a,size_t n)
{
	int i=(n-2)/2;//最后一个节点的父亲
	for (;i>=0;i--)
	{
		AdjustDownS(a,n,i);//向下调整
	}
}
void AdjustDownS(Datatype *a,size_t n,int k)//小堆
{
	int parent=k;
	int child=parent*2+1;
	while (child<n)
	{
		if (a[child+1]<a[child] && child+1<n)//俩个孩子选大的
		{
			++child;
		}
		if (a[parent]>a[child])//若父亲大于儿子则交换值
		{
			Datatype tmp=a[parent];
			a[parent]=a[child];
			a[child]=tmp;

			parent=child;//
			child=parent*2+1;用依次调整
		}
		else
		{
			break;
		}
	}
}

TopK问题:

首先构建TopK函数:查找最大的前K项 需建立小堆 反之大堆

void TopK(Datatype* a, size_t n, size_t k)//找出最大的前K项
{
	int j;
	int i=(n-2)/2;
	for (;i>=0;i--)//找最大的前K项 需要创建小堆
	{
		AdjustDownS(a,n,i);
	}
	for (j=k;j<n;j++)//从K后进行比较
	{
		if (a[0]<a[j])//大的进行值替换
		{
			a[0]=a[j];
			AdjustDownS(a,k,0);//小堆调整
		}
	}
	for (j=1;j<=k;j++)
	{
		printf("%d ",a[j-1]);//打印最大的前K项
	}
}

TopK问题测试用例:

void Test1()
{
	int i;
	Datatype a[]={10,11, 13, 12, 16, 18, 15, 17, 14, 19};
	Datatype NArray[1000]; 
	srand(time(0)); 
	for (i = 0; i < 1000; ++i) 
	{ 
		NArray[i] = rand()%10000; 
	} 

	NArray[30] = 10001; 
	NArray[350] = 10002; 
	NArray[999] = 10003; 
	NArray[158] = 10004; 
	NArray[334] = 10005; 

	TopK(NArray, 1000, 5); 
	
	//MakeHeap(a,sizeof(a)/sizeof(a[0]));
}

优先级序列问题:

首先创建结构体:

typedef int Datatype;
typedef struct PriorityQueue
{
	Datatype _a[N];
	size_t _size;
}PriorityQueue;

在一个有序的堆里插入一个数 应用向上调整:

void AdjustUp(Datatype *a,int child)//大堆
{
	int parent=(child-1)/2;
	while (parent>=0)
	{
		if (a[parent]<a[child])
		{
			Datatype tmp=a[parent];
			a[parent]=a[child];
			a[child]=tmp;

			child=parent;
			parent=(child-1)/2;
		}
		else
		{
			break;
		}
	}
}

然后是优先级的各种的函数构造:

void PriorityQueueInit(PriorityQueue* q)//优先级初始化
{
	assert(q);
	memset(q->_a,0,sizeof(Datatype));
	q->_size=0;
	
}
void PriorityQueuePush(PriorityQueue* q, Datatype x)//在一个有序的堆里插入
{
	assert(q);
	if (q->_size==N)
	{
		printf("Priority Queue Full!!!\n");
		return;
	}
	q->_a[q->_size]=x;
	q->_size++;
	AdjustUp(q->_a,q->_size-1);//向上调整大的往上调
}
void PriorityQueuePop(PriorityQueue* q)//出堆 最大的优先出
{
	assert(q);
	if (q->_size==0)
	{
		printf("Priority Queue Empty!!!\n");
		return;
	}
	q->_a[0]=q->_a[q->_size];
	--q->_size;
	AdjustDownD(q->_a,q->_size,0);//出后 进行大堆调整
}
Datatype PriorityQueueTop(PriorityQueue* q)
{
	assert(q);
	return q->_a[0];
}
size_t PriorityQueueSize(PriorityQueue* q)
{
	return q->_size;
}
size_t PriorityQueueEmpty(PriorityQueue* q)
{
	assert(q);
	return q->_size>0?1:0;
}

优先级测试用例:

void Test2()
{

	PriorityQueue q; 
	PriorityQueueInit(&q); 
	PriorityQueuePush(&q, 5); 
	PriorityQueuePush(&q, 2); 
	PriorityQueuePush(&q, 3); 
	PriorityQueuePush(&q, 7); 
	PriorityQueuePush(&q, 6); 
	PriorityQueuePush(&q, 1); 
	PriorityQueuePush(&q, 4); 

	while (PriorityQueueEmpty(&q) != 0) 
	{ 
		printf("%d ", PriorityQueueTop(&q)); 
		PriorityQueuePop(&q); 
	} 
	printf("\n"); 
	
}

堆排序问题:

void HeapSort(Datatype* a, size_t n)//升序 堆排序
{
	int i,j;
	int tmp;
	for (i=(n-2)/2;i>=0;i--)
	{
		AdjustDownD(a,n,i);//如果要构建升序,则需要建大堆
	}
	
	for (j=n-1;j>=0;j--)//最大的替换到后边 然后在大堆排序
	{
		tmp=a[0];
		a[0]=a[j];
		a[j]=tmp;

		AdjustDownD(a,j,0);
	}
	for (i=0;i<n;i++)
	{
		printf("%d ",a[i]);
	}
}

堆排序测试用例:

void Test3()
{
	int i;
	Datatype a[]={10,11, 13, 12, 16, 18, 15, 17, 14, 19};
	HeapSort(a,sizeof(a)/sizeof(a[0]));

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值