堆中数据的插入与删除(向上调整与向下调整算法)

对堆中数据进行了插入和删除后通常会破坏原本堆的排列结构,需要通过对堆进行调整来恢复大堆或者小堆的排列

这里假设原来的堆为小堆,所有孩子节点都大于其祖先节点,逻辑结构如下

                                        堆中数据的插入与删除(向上调整与向下调整算法)_第1张图片

向上调整:要求从该节点的父节点开始往上是一个堆,用于堆的插入,时间复杂度为logn

       堆的插入是在堆的末尾插入数据,现在插入一个值为10的节点,设该节点为child

        先找到其父亲parent = (child - 1) / 2;

        如果孩子的值小于父亲则交换,否则break。

                交换后孩子和父亲都向上走一层child = parent; parent = (child - 1) / 2;

        重复交换,直到child为根节点

                10<28,交换  堆中数据的插入与删除(向上调整与向下调整算法)_第2张图片

                10<18,交换堆中数据的插入与删除(向上调整与向下调整算法)_第3张图片

                10<15,交换堆中数据的插入与删除(向上调整与向下调整算法)_第4张图片

               

                10为根节点,停止最后结果如图所示堆中数据的插入与删除(向上调整与向下调整算法)_第5张图片

void HeapPush(HP* php, HPDataType x) {
	assert(php);

	//扩容
	if (php->size == php->capacity) {
		HPDataType* tmp = (HPDataType*)realloc(php->arr, sizeof(HPDataType) * (php->capacity+1)*2);
		if (tmp == NULL) {
			perror("realloc is fail!\n");
			exit(-1);
		}
		else {
			php->arr = tmp;
			php->capacity = (php->capacity + 1) * 2;
		}

	}

	//放数据
	php->arr[php->size] = x;
	php->size++;

	//排序
	//传入 数组 和 插入的元素下标,因为size前面++了所以这里要-1
	AdjustUp(php->arr, php->size - 1);

}


//向上调整:要求从该节点的父节点开始往上是一个堆,时间复杂度为logn
void AdjustUp(HPDataType* arr, int child) {
	//找到parent
	int parent = (child - 1) / 2;
	//当孩子不为根进入循环
	while (child > 0) {
		//如果孩子的值小于父亲则交换,否则break
		if (arr[child] < arr[parent]) {
			swap(&arr[child], &arr[parent]);
			//孩子和父亲都上走一层
			child = parent;
			parent = (child - 1) / 2;
		}
		else {
			break;
		}
	}
}

向下调整:要求从该节点子节点开始往下是一个堆,用于堆的删除,时间复杂度为logn

        堆的删除是删除堆顶的数据,将堆顶的数据与最后一个数据一换,然后删除数组最后一个数据,再进行向下调 ,整算法。

        现在删除堆顶数据10,先将其与堆尾数据互换堆中数据的插入与删除(向上调整与向下调整算法)_第6张图片

        再删除堆尾数据堆中数据的插入与删除(向上调整与向下调整算法)_第7张图片

        对堆中数据进行向下调整 堆中数据的插入与删除(向上调整与向下调整算法)_第8张图片

        

        设根节点为parent,找到其左孩子childleft = parent * 2 + 1;右孩子childright = parent * 2 + 2;

        选出值较小的孩子与parent交换

                交换完后parent和child的向下走一层,parent = child; child = parent * 2 + 1;

                重复交换,直到child放回最后一层(child原来就是从最后一层换上来的)

        15<19,与15交换堆中数据的插入与删除(向上调整与向下调整算法)_第9张图片

        18<25,与18交换堆中数据的插入与删除(向上调整与向下调整算法)_第10张图片

        此时没有右孩子,与37交换,28在最后一层,停止堆中数据的插入与删除(向上调整与向下调整算法)_第11张图片

      

void HeapPop(HP* php) {
	assert(php);
	assert(php->size > 0);

	//交换根和最后一个孩子,因为php->size = 元素个数 = 下一元素的插入位置,所以要减一才是末尾元素的位置
	swap(&php->arr[0], &php->arr[php->size-1]);
	//删除
	php->size--;
	
	//向下调整
	AdjustDown(php->arr, php->size, 0);

}


//向下调整:要求从该节点子节点开始往下是一个堆,时间复杂度为logn
void AdjustDown(HPDataType* arr, int size, int parent) {
	assert(arr);

	//选出较大的孩子,默认左孩子大,不能选右孩子,因为右孩子可能不存在
	int child = parent * 2 + 1;
	//当child存在(child

你可能感兴趣的:(算法,开发语言,c语言,数据结构)