文章目录
1.树

树的表示

左孩子右兄弟表示法
struct Node
{
struct Node* _firstChild1;
struct Node* _pNextBrother;
int _data;
}

双亲表示法

2.二叉树

满二叉树&完全二叉树

性质

存储方式
顺序存储
链式存储

遍历顺序
- 前序遍历 先根遍历(根左右)
- 中序遍历 中根遍历(左根右)
- 后序遍历 后根遍历(左右根)
- 层序遍历 一层一层走


TreeSize
void TreeSize(BTNode* root, int* psize)
{
if (root == NULL)
{
return;
}
++(*psize);
TreeSize(root->left, psize);
TreeSize(root->right, psize);
}
int size = 0;
TreeSize(A, &size);
printf("TreeSize::%d\n", size);
size = 0;
TreeSize(A, &size);
printf("TreeSize::%d\n", size);

int TreeSize(BTNode* root)
{
return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
printf("TreeSize::%d\n", TreeSize(A));
printf("TreeSize::%d\n", TreeSize(A));
TreeLeafSize
int TreeLeafSize(BTNode* root)
{
if (root == NULL)
{
return 0;
}
if (root->left == NULL && root->right == NULL)
{
return 1;
}
return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}
printf("TreeSize::%d\n", TreeLeafSize(A));
TreeKLevelSize
int TreeKLevelSize(BTNode* root, int k)
{
if (root == NULL)
{
return 0;
}
if (1 == k)
{
return 1;
}
return TreeKLevelSize(root->left, k - 1) +
TreeKLevelSize(root->right, k - 1);
}
BinaryTreeDestroy
void BinaryTreeDestroy(BTNode* root)
{
if (root == NULL)
{
return;
}
BinaryTreeDestroy(root->left);
BinaryTreeDestroy(root->right);
free(root);
}
BinaryTreeDestroy(A);
A = NULL;
DFS
BFS

void TreeLevelOrder(BTNode* root)
{
Queue q;
QueueInit(&q);
if (root)
{
QueuePush(&q, root);
}
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
QueuePop(&q);
printf("%c ", front->data);
if (front->left != NULL)
{
QueuePush(&q, front->left);
}
if (front->right != NULL)
{
QueuePush(&q, front->right);
}
}
QueueDestroy(&q);
}
TreeLevelOrder(A);
struct BinaryTreeNode;
typedef struct BinaryTreeNode* QDataType;
BinaryTreeComplete
bool BinaryTreeComplete(BTNode* root)
{
Queue q;
QueueInit(&q);
if (root != NULL)
{
QueuePush(&q, root);
}
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
QueuePop(&q);
if (front == NULL)
{
break;
}
QueuePush(&q, front->left);
QueuePush(&q, front->right);
}
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
QueuePop(&q);
if (front != NULL)
{
return false;
}
}
QueueDestroy(&q);
return true;
}
3.堆

假设父亲下标是parent
leftchild = parent*2 + 1;
rightchild= parent*2 + 2;
可以推出==>
parent = (child-1) / 2
(6-1) / 2 => 2
堆排序的实现

AdjustDown
void Swap(int* p1, int* p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
void AdjustDown(int* a, int n, int parent)
{
int child = parent * 2 + 1;
while (child < n)
{
if (child + 1 < n && a[child + 1] < a[child])
{
child++;
}
if (a[child] < a[parent])
{
Swap(&a[parent], &a[child]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
建堆算法

for (int i = (sz - 1 - 1) / 2; i >= 0; i--)
{
AdjustDown(arr, sz, i);
}


HeapSort
HeapSort(int* arr, int sz)
{
for (int i = (sz - 1 - 1) / 2; i >= 0; i--)
{
AdjustDown(arr, sz, i);
}
int end = sz - 1;
while (end > 0)
{
Swap(&arr[0], &arr[end]);
AdjustDown(arr, end, 0);
end--;
}
}
int main()
{
int arr[] = { 15,18,28,34,65,19,49,25,37,27 };
int sz = sizeof(arr) / sizeof(arr[0]);
HeapSort(arr, sz);
return 0;
}

堆的实现
Heap.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
#include<string.h>
typedef int HPDataType;
struct Heap
{
HPDataType* a;
int size;
int capacity;
};
typedef struct Heap HP;
void Swap(int* p1, int* p2);
void AdjustDown(int* a, int n, int parent);
void AdjustUp(int* a, int child);
void HeapInit(HP* php, HPDataType* a, int n);
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 HeapPrint(HP* php);
Test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"Heap.h"
void Test()
{
int a[] = { 15,18,28,34,65,19,49,25,37,27 };
int n = sizeof(a) / sizeof(a[0]);
HP hp;
HeapInit(&hp, a, n);
HeapPrint(&hp);
HeapPush(&hp, 8);
HeapPrint(&hp);
HeapPush(&hp, 88);
HeapPrint(&hp);
HeapPop(&hp);
HeapPrint(&hp);
HeapDestroy(&hp);
}
void TopK()
{
}
int main()
{
Test();
return 0;
}
Init&Destroy
void HeapInit(HP* php, HPDataType* a, int n)
{
assert(php);
php->a = (HPDataType*)malloc(sizeof(HPDataType) * n);
if (php->a == NULL)
{
printf("malloc fail\n");
exit(-1);
}
memcpy(php->a, a, sizeof(HPDataType) * n);
php->size = n;
php->capacity = n;
for (int i = (php->size - 1 - 1) / 2; i >= 0; i--)
{
AdjustDown(php->a, php->size, i);
}
}
void HeapDestroy(HP* php)
{
assert(php);
free(php->a);
php->a = NULL;
php->size = php->capacity = 0;
}
Print
void HeapPrint(HP* php)
{
for (int i = 0; i < php->size; i++)
{
printf("%d ", php->a[i]);
}
printf("\n");
int num = 0;
int levelSize = 1;
for (int i = 0; i < php->size; i++)
{
printf("%d ", php->a[i]);
num++;
if (num == levelSize)
{
printf("\n");
levelSize *= 2;
num = 0;
}
}
printf("\n");
printf("\n");
}
AdjustUp
void AdjustUp(int* a, int child)
{
int parent = (child - 1) / 2;
while (child > 0)
{
if (a[child] > a[parent])
{
Swap(&a[parent], &a[child]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
Push
void HeapPush(HP* php, HPDataType x)
{
assert(php);
if (php->size == php->capacity)
{
HPDataType* tmp = (HPDataType*)realloc(php->a, php->capacity * 2 * sizeof(HPDataType));
if (tmp == NULL)
{
printf("realloc fail\n");
exit(-1);
}
php->a = tmp;
php->capacity *= 2;
}
php->a[php->size] = x;
php->size++;
AdjustUp(php->a, php->size - 1);
}
Pop
void HeapPop(HP* php)
{
assert(php);
assert(php->size > 0);
Swap(&php->a[php->size - 1], &php->a[0]);
php->size--;
AdjustDown(php->a, php->size, 0);
}
Top
HPDataType HeapTop(HP* php)
{
assert(php);
assert(php->size > 0);
return php->a[0];
}
Size
int HeapSize(HP* php)
{
assert(php);
return php->size;
}
Empty
bool HeapEmpty(HP* php)
{
assert(php);
return php->size == 0;
}
练习
剑指 Offer 40. 最小的k个数
int* getLeastNumbers(int* arr, int arrSize, int k, int* returnSize){
HP hp;
HeapInit(&hp, arr, arrSize);
int* retArr = (int*)malloc(sizeof(int)*k);
for(int i=0; i<k; i++)
{
retArr[i] = HeapTop(&hp);
HeapPop(&hp);
}
HeapDestroy(&hp);
*returnSize = k;
return retArr;
}
int* getLeastNumbers(int* arr, int arrSize, int k, int* returnSize){
if(k == 0)
{
*returnSize = 0;
return NULL;
}
int* retArr = (int*)malloc(sizeof(int)*k);
for(int i=0; i<k; i++)
{
retArr[i] = arr[i];
}
for(int j=(k-1-1)/2; j>=0; j--)
{
AdjustDown(retArr,k,j);
}
for(int i=k; i<arrSize;++i)
{
if(arr[i] < retArr[0])
{
retArr[0] = arr[i];
AdjustDown(retArr,k,0);
}
}
*returnSize = k;
return retArr;
}
104. 二叉树的最大深度
int maxDepth(struct TreeNode* root){
if(root == NULL)
{
return 0;
}
return maxDepth(root->left)>maxDepth(root->right)?maxDepth(root->left)+1:maxDepth(root->right)+1;
}

int maxDepth(struct TreeNode* root){
if(root == NULL)
{
return 0;
}
int lMaxDepth = maxDepth(root->left);
int rMaxDepth = maxDepth(root->right);
return lMaxDepth>rMaxDepth?lMaxDepth+1:rMaxDepth+1;
}
int maxDepth(struct TreeNode* root){
if(root == NULL)
{
return 0;
}
return fmax(maxDepth(root->left),maxDepth(root->right))+1;
}
965. 单值二叉树
bool isUnivalTree(struct TreeNode* root){
if(root == NULL)
{
return true;
}
if(root->left != NULL && root->left->val != root->val)
{
return false;
}
if(root->right != NULL && root->right->val != root->val)
{
return false;
}
return isUnivalTree(root->left) && isUnivalTree(root->right);
}
144. Binary Tree Preorder Traversal
int TreeSize(struct TreeNode* root)
{
return root == NULL ? 0:TreeSize(root->left) + TreeSize(root->right) + 1;
}
struct TreeNode* _preorderTraversal(struct TreeNode* root, int* arr, int* pi)
{
if(root==NULL)
return;
arr[(*pi)++] = root->val;
_preorderTraversal(root->left,arr,pi);
_preorderTraversal(root->right,arr,pi);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize){
*returnSize = TreeSize(root);
int* arr = (int*)malloc(sizeof(int)*(*returnSize));
int i = 0;
_preorderTraversal(root,arr,&i);
return arr;
}
100. Same Tree
bool isSameTree(struct TreeNode* p, struct TreeNode* q){
if(p==NULL && q==NULL)
return true;
if(p==NULL || q==NULL)
return false;
if(p->val != q->val)
return false;
return isSameTree(p->left, q->left)
&& isSameTree(p->right, q->right);
}
226. Invert Binary Tree
struct TreeNode* invertTree(struct TreeNode* root){
if(root == NULL)
return NULL;
struct TreeNode* left = invertTree(root->left);
struct TreeNode* right = invertTree(root->right);
root->left = right;
root->right = left;
return root;
}
101. Symmetric Tree
bool _isSymmetric(struct TreeNode* left,struct TreeNode* right)
{
if(left == NULL && right == NULL)
return true;
if(left == NULL || right == NULL)
return false;
if(left->val != right->val)
return false;
return _isSymmetric(left->right, right->left)
&& _isSymmetric(left->left, right->right);
}
bool isSymmetric(struct TreeNode* root){
if(root == NULL)
return true;
bool ret = _isSymmetric(root->left,root->right);
return ret;
}
bool isSymmetric(struct TreeNode* root){
if(root == NULL)
return true;
root->right = invertTree(root->right);
bool ret = isSameTree(root->left, root->right);
return ret;
}
572. Subtree of Another Tree
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){
if(root == NULL)
return false;
if(isSameTree(root,subRoot))
return true;
return isSubtree(root->left,subRoot)
|| isSubtree(root->right,subRoot);
}
110. Balanced Binary Tree
bool isBalanced(struct TreeNode* root){
if(root == NULL)
return true;
int leftDepth = maxDepth(root->left);
int rightDepth = maxDepth(root->right);
return abs(leftDepth-rightDepth) < 2
&& isBalanced(root->left)
&& isBalanced(root->right);
}
时间复杂度分析 O(N^2)
假设是满二叉树(最坏情况下)
isBalanced递归了N次(其实就是深度优先)
每次递归:N N/2 N/2 N/4 N/4 ...
要求:优化到O(N)
由于是自顶向下递归,因此对于同一个节点,函数maxDepth会被重复调用,导致时间复杂度较高。
bool _isBalanced(struct TreeNode* root, int* ph)
{
if(root == NULL)
{
*ph = 0;
return true;
}
int leftHeight = 0;
if(_isBalanced(root->left,&leftHeight) == false)
return false;
int rightHeight = 0;
if(_isBalanced(root->right,&rightHeight) == false)
return false;
*ph = fmax(leftHeight,rightHeight) + 1;
return fabs(leftHeight-rightHeight) < 2;
}
bool isBalanced(struct TreeNode* root){
int height = 0;
return _isBalanced(root, &height);
}
清华大学复试二叉树遍历

#include<stdio.h>
#include<stdlib.h>
typedef struct TreeNode
{
char val;
struct TreeNode* left;
struct TreeNode* right;
}TNode;
TNode* CreateTree(char* a, int* pi)
{
if (a[*pi] == '#')
{
(*pi)++;
return NULL;
}
TNode* root = (TNode*)malloc(sizeof(TNode));
if (root == NULL)
{
printf("malloc fail\n");
exit(-1);
}
else
{
root->val = a[*pi];
(*pi)++;
root->left = CreateTree(a, pi);
root->right = CreateTree(a, pi);
return root;
}
}
void InOrder(TNode* root)
{
if (root == NULL)
{
return;
}
InOrder(root->left);
printf("%c ", root->val);
InOrder(root->right);
}
int main()
{
char arr[30] = { 0 };
gets(arr);
int i = 0;
TNode* root = CreateTree(arr, &i);
InOrder(root);
return 0;
}