堆操作综合

typedef struct Heap
{
	int* a;
	int size;
	int capcity;
}HP;

堆的结构,要有两个指针,一个头一个尾,数组情况下略显多余,但链表情况必不可少

void heapinit(HP* point)
{
	assert(point);
	point->a = NULL;
	point->size = point->capcity = 0;
}
void heapdestory(HP* point)
{
	assert(point);
	point->size = point->capcity = 0;
	free(point->a);
	point->a = NULL;
}

堆的初始化与释放,和栈与队列类似

void heappush(HP* point, int x)
{
	assert(point);
	if (point->a == NULL)
	{
		point->a = (int*)malloc(sizeof(int) *5);
		point->capcity = 5;
	}
	point->a[point->size] = x;
	point->size++;
	adjustup(point, point->size-1);
}

堆元素的插入,首先当堆的状态只为初始化时,需要给指针一段空间,然后将元素放到堆的末尾,然后向上调整

void adjustup(int *a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] > a[parent])
		{
			int c = a[child];
			a[child] = a[parent];
			a[parent] = c;
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

向上调整的原理,这是一个大堆,父节点必须比子节点大,如果相反那么交换后仍需检查其他相关节点是否有问题,首先根据满二叉树的性质找到当前子节点的父节点,如果不符合性质则交换,再继续检查。

void heappop(HP* point)
{
	assert(point);
	assert(point->size != 0);
	int c = point->a[0];
	point->a[0] = point->a[point->size - 1];
	point->a[point->size - 1] = c;
	point->size--;
	adjustdown(point, point->size);
}

堆的删除:指删除堆顶元素,方法为将堆顶和堆底元素互换,然后让size指针减一,彻底抹除没有必要,然后向上调整

void adjustdown(int *a, int num,int b)//左右子树必须是堆
{
	int parent = b;
	int child =parent * 2 + 1;
	while (child a[child + 1]&&child+1 a[parent])
		{
			int c = a[child];
			a[child] =a[parent];
			a[parent] = c;
		
			parent = child;
			child = parent * 2 + 1;//继续向下调
			
		}
		else
		{
			break;
		}
	}
}

向下调整:与向上调整一样,此处为小堆操作,父节点必须大,而此处的关键在于找到左孩子右孩子中的大孩子,如果不符合与父亲交换,否则存在还需寻找一次的风险,由于只交换了两个元素,所以整体二叉树结构不变,而且只要一次符合那么下面的元素就都符合了

bool heapempty(HP* point)
{
	assert(point);
	return point->size == 0;
}

判空

void heapsort(int* a, int num)
{
	HP heap1;
	heappinit(&heap1);
	for (int i = 0; i < sizeof(a) / sizeof(int); ++i)
	{
		heappush(&heap1, a[i]);

	}
	int j = 0;
	while (heap1.size != 0)
	{
		int top1 = heap1.a[0];
		a[j++] = top1;
		heappop(&heap1);
	}
	//free(&heap1.a);
	//heap1.a = NULL;
	//heap1.size = heap1.capcity = 0;



}

堆排序(必须建堆)一:先建堆,然后返回堆顶元素,再删除堆顶元素,直到将整个堆重新排列在目标数组中,完成排序,弊端在于空间复杂度与拷贝数据

void heapsort2(int* a, int n)
{
	for (int i = 1; i < n; i++)
	{
		adjustup(a, i);
	}
	int end = n - 1;
	while (end>0)
	{
		int c = a[0];
		a[0] = a[end];
		a[end] = c;
		adjustdown(a, end, 0);
		end--;
	}
}

堆排序二:如果是降序,则建小堆,建完首尾交换,选出最小的放在最后面,然后剩下的元素向下调整选出次小的,然后再首尾交换,以此类推,升序相反

你可能感兴趣的:(数据结构,算法,数据结构)