首页 > 其他分享 >堆排序——C语言描述

堆排序——C语言描述

时间:2023-03-19 18:55:32浏览次数:46  
标签:NodeIndex Arr int 堆排序 结点 C语言 ---------- Test 描述

堆排序——C语言描述

目录

0 测试用例框架

https://blog.csdn.net/m0_59469991/article/details/127137119?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22127137119%22%2C%22source%22%3A%22m0_59469991%22%7D

1 定义

(1)算法思想:

将待排序的序列构造成一个大顶堆。将堆顶元素与数组末尾的元素进行交换。数组长度减一,并重新调整堆。反复执行,即可得有序序列。

(2)利用二叉树的性质:

一个完全二叉树,按编号0开始进行层序遍历。

① 当i为0时,无双亲结点;

② 当i有左孩子时,左孩子的编号为2i + 1;

③ 当i有右孩子时,右孩子的编号为2i + 2;

(3)时间复杂度

时间复杂度为nlogn。创建堆复杂度最大为nlogn(假如每个结点之后的孩子结点都需要交换,根结点需要交换的次数为完成二叉树的深度(|logn| + 1),类似等差数列)。调整堆复杂度最大度也是nlogn(每次交换堆顶,重新调整堆,从根结点开始调整,最大调整次数为为二叉树的深度,(|logi| + 1)),需要调整n-1次,所以复杂度为nlogn)。

注意:

(1)HeapSort:

① 创建堆:从最后一个非叶子结点开始((Num - 1)/2),到根结点结束,所有的非叶子结点都要处理;

② 调整堆: NodeIndex无需等于0,因为只剩一个元素时无需再交换和调整;

③ 调整堆:因为只交换了第一个元素,所以调整堆的时候只对从第一个结点开始调整,长度也要递减。

(1) HeapAdjust:

① 使用循环的原因是交换过的结点是需要再次与他的孩子结点进行调整的;

② 从左孩子结点开始,每次都取结点的左孩子;

③ 先孩子结点相互比较,然后与双亲结点进行比较;

④ 孩子结点比较后使用i++的方式,是了保证下一个循环使用交换过结点进行比较.

⑤ 如发生了交换,NoteIndex = i, 进行迭代

2 代码

void Swap(int *Mem01, int *Mem02) {
	int Tmp = *Mem01;
	*Mem01 = *Mem02;
	*Mem02 = Tmp;
}

void HeapAdjust(int *Arr, int NodeIndex, int Num) {
	int i;

	for (i = 2 * NodeIndex + 1; i < Num; i = 2 * i + 1) {
		if (((i + 1) < Num) && (Arr[i] < Arr[i + 1])) {
			i++;
		}

		if (Arr[i] < Arr[NodeIndex]) {
			break;
		} else {
			Swap(&Arr[i], &Arr[NodeIndex]);
		}

		NodeIndex = i;
	}
}

/*HeapSort*/
// { 1, 3, 2, 5, 4, 0 }
void HeapSort(int *Arr, int Num) {
	int NodeIndex;

	if ((Arr == NULL) || (Num <= 1)) {
		return ;
	}

	for (NodeIndex = (Num - 1) / 2; NodeIndex >= 0; --NodeIndex) {
		HeapAdjust(Arr, NodeIndex, Num);
	}

	for (NodeIndex = Num - 1; NodeIndex > 0; --NodeIndex) {
		Swap(&Arr[0], &Arr[NodeIndex]);
		HeapAdjust(Arr, 0, NodeIndex);
	}
}

4 测试用例

void TestCmpArr(int *CmpArr, int Num, int *Arr) {
	int Index = 0;
	int CmpNum = 0;

	TestNum++;

	for (Index = 0; Index < Num; ++Index) {
		if (CmpArr[Index] == Arr[Index]) {
			CmpNum++;
		}
	}

	if (CmpNum != Num) {
		printf("Incorrect!\n");
		FaildNum++;
	}
	else {
		printf("Correct!\n");
		PassNum++;
	}
}

/*TestHeapSort*/
void TestHeapSort(void) {
	/*Test01: Normal*/
	int Arr01[] = { 1, 3, 2, 5, 4, 0 };
	int Num01 = 6;
	int CmpArr01[] = { 0, 1, 2, 3, 4, 5 };
	//int CmpArr01[] = { 5, 4, 2, 3, 1, 0 };

	/*Test02: Normal*/
	int Arr02[] = { 7, 6, 5, 4, 3, 2, 1, 0 };
	int Num02 = 8;
	int CmpArr02[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
	//int CmpArr02[] = { 7, 6, 5, 4, 3, 2, 1, 0 };

	/*Test03: Two Mem*/
	int Arr03[] = { 1, 0 };
	int Num03 = 2;
	int CmpArr03[] = { 0, 1 };
	//int CmpArr03[] = { 1, 0 };

	/*Test04: Only 1 Mem*/
	int Arr04[] = { 0 };
	int Num04 = 1;
	int CmpArr04[] = { 0 };

	printf("-------Test start----------\n");
	InitNum();

	/*Test01*/
	printf("\n-------Test 01----------\n");
	HeapSort(Arr01, Num01);

	TestCmpArr(CmpArr01, Num01, Arr01);

	/*Test02*/
	printf("\n-------Test 02----------\n");
	HeapSort(Arr02, Num02);
	PrintArr(Arr02, Num02);
	TestCmpArr(CmpArr02, Num02, Arr02);

	/*Test03*/
	printf("\n-------Test 03----------\n");
	HeapSort(Arr03, Num03);
	PrintArr(Arr03, Num03);
	TestCmpArr(CmpArr03, Num03, Arr03);

	/*Test04*/
	printf("\n-------Test 04----------\n");
	HeapSort(Arr04, Num04);
	PrintArr(Arr04, Num04);
	TestCmpArr(CmpArr04, Num04, Arr04);

	/*Test Result*/
	printf("\n-------Test result----------\n");
	TestResult();
}

打印结果

-------Test start----------

-------Test 01----------

Arr[0] = 0

Arr[1] = 1

Arr[2] = 2

Arr[3] = 3

Arr[4] = 4

Arr[5] = 5

Correct!

-------Test 02----------

Arr[0] = 0

Arr[1] = 1

Arr[2] = 2

Arr[3] = 3

Arr[4] = 4

Arr[5] = 5

Arr[6] = 6

Arr[7] = 7

Correct!

-------Test 03----------

Arr[0] = 0

Arr[1] = 1

Correct!

-------Test 04----------

Arr[0] = 0

Correct!

-------Test result----------

Print test result;

TestNum = 4, PassNum = 4, FaildNum = 0

标签:NodeIndex,Arr,int,堆排序,结点,C语言,----------,Test,描述
From: https://www.cnblogs.com/meditatorss/p/17233925.html

相关文章

  • C语言学习第二天
    1、#define_CRT_SECURE_NO_WARNINGS1#include<stdio.h>intmain(){chararr1[]="abc";//"abc"--'a''b''c''\0',\0表示字符串的结束标志//数据在计算机上存储的时......
  • C语言函数大全--b开头的函数
    C语言函数大全本篇介绍C语言函数中b开头的函数1.bar1.1函数说明函数声明函数功能voidbar(intleft,inttop,intright,intbottom);画一个二维条形图......
  • C语言中%d,等等% 的用法,和意义
      转载-----%d是占位符,%是引导符,d表示十进制整数的形式例如我用键盘输入一个整数给变量a写成:scanf("%d",&a);%d占得就是a的位再如我在显示器上输出变量a的值......
  • C语言_求最大公约数和最小公倍数
    #include<stdio.h>intmain(){ intn1,n2,x,y,temp;printf("请输入两个数用空格隔开:\n"); scanf("%d%d",&n1,&n2); x=n1>n2?n1:n2;//保存较大数 y=n1+n2-x; ......
  • 实验2 C语言输入输出和控制语句应用编程
    实验任务11#include<stdio.h>2#include<stdlib.h>3#include<time.h>4#defineN55#defineR15866#defineR27017intmain()8{9intn......
  • 属性描述符defineProperty
    属性描述符是会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。属性描述符有两种主要形式:数据描述符和存取描述符。数据描述符是一个具有值的属......
  • C语言自定义数据类型之结构体
    一、结构体1.1结构体的声明语法struct对象名{成员列表;};1.2结构体声明的解释结构体其实与我们在数学中学过的集合本质相同比如,现在有一个描述房子的集合,集合里有许多元素,......
  • 初识c语言
    1.程序语言C语言是目前极为流行的一种计算机程序设计语言,它既具有高级语言的功能,又具有汇编语言的一些特性,且支持ANSIC。C语言的特点:通用性及易写易读,是一种结构化程序......
  • C语言_求n阶乘
    #include"stdio.h"main(){ longi,sum; printf("请输入一需要求阶乘的数:"); scanf("%ld",&i); sum=1; while(i>1) { sum=sum*i; i--; } printf("\n这个数......
  • C语言_输入小写字母输出大写字母
    #include"stdio.h"main(){ charx; printf("请输入一个小写字母:"); scanf("%c",&x); switch(x) {case'a': printf("这个字母的大写是A"); break; case'b': pri......