赞
踩
注意:树形结构中,子树之间不能有交集,否则就不是树形结构
节点的度:一个节点含有的子树的个数称为该节点的度; 如上图:A的为6
叶节点或终端节点:度为0的节点称为叶节点; 如上图:B、C、H、I...等节点为叶节点
typedef int DataType ;struct Node{struct Node * _firstChild1 ; // 第一个孩子结点struct Node * _pNextBrother ; // 指向其下一个兄弟结点DataType _data ; // 结点中的数据域};
从上图可以看出:
性质练习题:
1. 某二叉树共有 399 个结点,其中有 199 个度为 2 的结点,则该二叉树中的叶子结点数为( )A 不存在这样的二叉树B 200C 198D 1992. 下列数据结构中,不适合采用顺序存储结构的是( )A 非完全二叉树B 堆C 队列D 栈3. 在具有 2n 个结点的完全二叉树中,叶子结点个数为( )A nB n+1C n-1D n/24. 一棵完全二叉树的节点数位为 531 个,那么这棵树的高度为( )A 11B 10C 8D 125. 一个具有 767 个节点的完全二叉树,其叶子节点个数为()A 383B 384C 385D 386答案:1.B2.A3.A4.B5.B
typedef int BTDataType ;// 二叉链struct BinaryTreeNode{struct BinTreeNode * _pLeft ; // 指向当前节点左孩子struct BinTreeNode * _pRight ; // 指向当前节点右孩子BTDataType _data ; // 当前节点值域}// 三叉链struct BinaryTreeNode{struct BinTreeNode * _pParent ; // 指向当前节点的双亲struct BinTreeNode * _pLeft ; // 指向当前节点左孩子struct BinTreeNode * _pRight ; // 指向当前节点右孩子BTDataType _data ; // 当前节点值域} ;
int array [] = { 27 , 15 , 19 , 18 , 28 , 34 , 65 , 49 , 25 , 37 };
因此:建堆的时间复杂度为O(N)。故实际中我们选用向下调整建堆
简单理解:
- // O(N*logN)
- for (int i = 0; i < n; i++) //插入N个数据,每个数据挪动logN次(因为h=log(N+1)),合计N*logN
- {
- AdjustUp(a, i); //logN
- }
其实光看最后一层(占了一半的结点)就知道N/2个数据挪动logN次,即时间复杂度:O(N*logN)
- #pragma once
- #include<stdio.h>
- #include<stdlib.h>
- #include<assert.h>
- #include<stdbool.h>
-
- typedef int HPDataType;
-
- typedef struct Heap
- {
- HPDataType* a;
- int size;
- int capacity;
- }HP;
-
- void HeapInit(HP* php);
- void HeapDestroy(HP* php);
- void HeapPush(HP* php, HPDataType x);
- // 规定删除堆顶(根节点)
- void HeapPop(HP* php);
- HPDataType HeapTop(HP* php);
- int HeapSize(HP* php);
- bool HeapEmpty(HP* php);
-
- void Swap(HPDataType* p1, HPDataType* p2);
- void AdjustUp(HPDataType* a, int child);
- void AdjustDown(HPDataType* a, int size, int parent);
- #include"Heap.h"
-
- // 小堆
- void HeapInit(HP* php)
- {
- assert(php);
-
- php->a = NULL;
- php->size = 0;
- php->capacity = 0;
- }
-
- void HeapDestroy(HP* php)
- {
- assert(php);
-
- free(php->a);
- php->a = NULL;
- php->size = php->capacity = 0;
- }
-
- void Swap(HPDataType* p1, HPDataType* p2)
- {
- HPDataType tmp = *p1;
- *p1 = *p2;
- *p2 = tmp;
- }
-
- void AdjustUp(HPDataType* a, int child)
- {
- int parent = (child - 1) / 2;
- while (child > 0)
- {
- if (a[child] < a[parent])
- {
- Swap(&a[child], &a[parent]);
- child = parent;
- parent = (child - 1) / 2;
- }
- else
- {
- break;
- }
- }
- }
-
- // O(logN)
- void HeapPush(HP* php, HPDataType x)
- {
- assert(php);
- if (php->size == php->capacity)
- {
- int newCapacity = php->capacity == 0 ? 4 : php->capacity * 2;
- HPDataType* tmp = (HPDataType*)realloc(php->a, newCapacity * sizeof(HPDataType));
- if (tmp == NULL)
- {
- perror("realloc fail");
- exit(-1);
- }
-
- php->a = tmp;
- php->capacity = newCapacity;
- }
-
- php->a[php->size] = x;
- php->size++;
-
- AdjustUp(php->a, php->size - 1);
- }
-
- void AdjustDown(int* a, int size, int parent)
- {
- int child = parent * 2 + 1;
-
- while (child < size)
- {
- // 假设左孩子小,如果解设错了,更新一下
- // child+1 < size 即没有右孩子,左孩子是最后一个
- if (child+1 < size && a[child + 1] < a[child])
- {
- ++child;
- }
-
- if (a[child] < a[parent])
- {
- Swap(&a[child], &a[parent]);
- parent = child;
- child = parent * 2 + 1;
- }
- else
- {
- break;
- }
- }
- }
-
- void HeapPop(HP* php)
- {
- assert(php);
- assert(php->size > 0);
-
- Swap(&php->a[0], &php->a[php->size - 1]);
- php->size--;
-
- AdjustDown(php->a, php->size, 0);
- }
-
- HPDataType HeapTop(HP* php)
- {
- assert(php);
- assert(php->size > 0);
-
- return php->a[0];
- }
-
- int HeapSize(HP* php)
- {
- assert(php);
-
- return php->size;
- }
-
- bool HeapEmpty(HP* php)
- {
- assert(php);
-
- return php->size == 0;
- }
- #include"Heap.h"
-
- int main()
- {
- int a[] = { 4,6,2,1,5,8,2,9};
- HP hp;
- HeapInit(&hp);
- for (int i = 0; i < sizeof(a) / sizeof(int); ++i)
- {
- HeapPush(&hp, a[i]);
- }
-
- /*int k = 3;
- while (k--)
- {
- printf("%d\n", HeapTop(&hp));
- HeapPop(&hp);
- }*/
-
- while (!HeapEmpty(&hp))
- {
- printf("%d ", HeapTop(&hp));
- HeapPop(&hp);
- }
- printf("\n");
-
- return 0;
- }
堆排序即利用堆的思想来进行排序,总共分为两个步骤:
- // 升序:建大堆
- void HeapSort(int* a, int n)
- {
- // 建大堆
- // O(N*logN)
- /*for (int i = 0; i < n; i++)
- {
- AdjustUp(a, i);
- }*/
-
- // O(N)
- for (int i = (n-1-1)/2; i >= 0; --i)
- {
- AdjustDown(a, n, i);
- }
-
- //O(N*logN),每次都从根节点开始向下调整高度次
- int end = n - 1;
- while (end > 0)
- {
- Swap(&a[0], &a[end]);
- AdjustDown(a, end, 0);
- --end;
- }
- }
TOP-K问题:即求数据集合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大。
- void CreateNDate()
- {
- // 造数据
- int n = 10000000;
- srand(time(0));
- const char* file = "data.txt";
- FILE* fin = fopen(file, "w");
- if (fin == NULL)
- {
- perror("fopen error");
- return;
- }
-
- for (int i = 0; i < n; ++i)
- {
- int x = (rand()+i) % 10000000;
- fprintf(fin, "%d\n", x);
- }
-
- fclose(fin);
- }
-
- void PrintTopK(const char* file, int k)
- {
- FILE* fout = fopen(file, "r");
- if (fout == NULL)
- {
- perror("fopen error");
- return;
- }
-
- // 建一个k个数小堆
- int* minheap = (int*)malloc(sizeof(int) * k);
- if (minheap == NULL)
- {
- perror("malloc error");
- return;
- }
-
- // 读取前k个,建小堆
- for (int i = 0; i < k; i++)
- {
- fscanf(fout, "%d", &minheap[i]);
- AdjustUp(minheap, i);
- }
-
- int x = 0;
- while (fscanf(fout, "%d", &x) != EOF)
- {
- if (x > minheap[0])
- {
- minheap[0] = x;
- AdjustDown(minheap, k, 0);
- }
- }
-
- for (int i = 0; i < k; i++)
- {
- printf("%d ", minheap[i]);
- }
- printf("\n");
-
- free(minheap);
- fclose(fout);
- }
-
- int main()
- {
- CreateNDate();
- PrintTopK("data.txt", 5);
-
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。