【C/C++数据结构与算法】C语言二叉树与堆

目录

一、二叉树

二、二叉树的层序遍历

三、堆


一、二叉树

二叉树特性:

  • 算法的核心思维:递归
  • 满二叉树:二叉树的层数为k,节点数为
  • 完全二叉树:二叉树的层数为k,前k - 1层是满的,第k层是连续的
  • 满二叉树是完全二叉树的子集
  • 任意二叉树:若叶子节点的个数为 n0,设度为2的节点个数为 n2,则 n0 = n2+1
  •  二叉树的第 i 层上最多有2^(i-1)个节点,有n个节点的满二叉树深度 h = lg(n+1)
  • 二叉树可顺序存储或链式存储

代码功能:

  • 二叉树的构建和销毁
  • 二叉树的先序、中序、后序遍历
  • 二叉树总节点数、叶子节点数、第k层节点数、深度、子树数量计算
#include 
#include 
#include 
 
typedef char BTData;
 
typedef struct BinaryTreeNode 
{
    BTData data;
    struct BinaryTreeNode* left;
    struct BinaryTreeNode* right;
}BTNode;
 
BTNode* BuyBTNode(BTData x) 
{
    BTNode* new = (BTNode*)malloc(sizeof(BTNode));
    new->data = x;
    new->left = new->right = NULL;
    return new;
}

//构建
BTNode* BinaryTreePreCreate(BTData* a, int* pi) 
{
    if (a[*pi] == '#')
    {
        (*pi)++;
        return NULL;
    }
    BTNode* root = BuyBTNode(a[(*pi)++]);
    root->left = BinaryTreePreCreate(a, pi);
    root->right = BinaryTreePreCreate(a, pi);
    return root;
}

//销毁
void BinaryTreeDestory(BTNode* root) 
{
    if (root == NULL)
        return;
    BinaryTreeDestory(root->left);
    BinaryTreeDestory(root->right);
    printf("%c ", root->data);
    free(root);
}

//前序
void PreOrder(BTNode* root) 
{
    if (root == NULL)
    {
        printf("# ");
        return;
    }
    printf("%c ", root->data);
    PreOrder(root->left);
    PreOrder(root->right);
}

//中序
void InOrder(BTNode* root) 
{
    if (root == NULL)
    {
        printf("# ");
        return;
    }
    InOrder(root->left);
    printf("%c ", root->data);
    InOrder(root->right);
}

//后序
void PastOrder(BTNode* root) 
{
    if (root == NULL)
    {
        printf("# ");
        return;
    }
    PastOrder(root->left);
    PastOrder(root->right);
    printf("%c ", root->data);
}

//计算总节点数
int BinaryTreeSize(BTNode* root) 
{
    return root == NULL ? 0 :
        BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}

//计算叶子节点数
int BinaryTreeLeafSize(BTNode* root) 
{
    if (root == NULL)
        return 0;
    if (root->left == NULL && root->right == NULL)
        return 1;
    return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}

//计算第k层节点数
int BinaryTreeLevelKSize(BTNode* root, int k) 
{
    assert(k >= 1);
    if (k == 1)
    {
        if (root)
            return 1;
        else
            return 0;
    }
    return BinaryTreeLevelKSize(root->left, k - 1) +
        BinaryTreeLevelKSize(root->right, k - 1);
}

//查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTData x) 
{
    if (root == NULL)
        return NULL;
    if (root->data == x)
        return root;
    BTNode* ret = BinaryTreeFind(root->left, x);
    if (ret)
        return ret;
    return BinaryTreeFind(root->right, x);
}

//计算深度
int BinaryTreeDepth(BTNode* root) 
{
    if (root == NULL)
        return 0;
    int left_depth = BinaryTreeDepth(root->left);
    int right_depth = BinaryTreeDepth(root->right);
    return left_depth > right_depth ? left_depth + 1 : right_depth + 1;
}

//计算子树数量
int TreeSize(BTNode* root) 
{
    if (root == NULL)
        return 0;
    return (root->left == NULL && root->right == NULL) ? 0 :
        (TreeSize(root->left) + TreeSize(root->right) + 1);
}
 
int main() 
{
    int i = 0;
    BTNode* root = BinaryTreePreCreate("123###45##6##", &i);        //用前序遍历进行构建二叉树
 
    printf("PreOrder:  ");
    PreOrder(root);            // 1 2 3 # # # 4 5 # # 6 # #
    printf("\n");
    printf("InOrder:   ");
    InOrder(root);            // # 3 # 2 # 1 # 5 # 4 # 6 #
    printf("\n");
    printf("PastOrder: ");
    PastOrder(root);        // # # 3 # 2 # # 5 # # 6 4 1
    printf("\n");
 
    printf("BinaryTreeSize: %d \n", BinaryTreeSize(root));
    printf("BinaryTreeLeafSize: %d\n", BinaryTreeLeafSize(root));
    printf("level3 BinaryTreeLevelKSize: %d\n", BinaryTreeLevelKSize(root, 3));
    BTNode* tmp = BinaryTreeFind(root, '5');
    if (tmp)
        printf("BinaryTreeFind: tmp->data == %c\n", tmp->data);
    else
        printf("BinaryTreeFind: tmp->data == NULL\n");
    printf("BinaryTreeDepth: %d\n", BinaryTreeDepth(root));
    printf("TreeSize: %d\n", TreeSize(root));
 
    printf("BinaryTreeDestory: ");
    BinaryTreeDestory(root);
    printf("\n");
    root = NULL;
    return 0;
}

二、二叉树的层序遍历

层序遍历思路:

  1. 利用队列,队列存入节点指针
  2. 先将根结点存入队列,pop一次
  3. 如果出队列的是空指针,则打印 '#';如果不是空指针,则将左右孩子节点的指针push入队列
#include 
#include 
#include 
using namespace std;

typedef char NodeData;

struct BTNode 
{
    NodeData data;
    BTNode* left;
    BTNode* right;

    BTNode(NodeData x)
        : data(x), left(nullptr), right(nullptr) 
    {}
};

BTNode* Create(NodeData* a, int& i) 
{
    if (a[i] == '#') 
    {
        ++i;
        return nullptr;
    }
    BTNode* root = new BTNode(a[i++]);
    root->left = Create(a, i);
    root->right = Create(a, i);
    return root;
}

void LevelOrder(BTNode* root) 
{
    queue q;
    q.push(root);
    while (!q.empty()) 
    {
        BTNode* front = q.front();
        q.pop();
        if (front) 
        {
            cout << front->data << ' ';
            q.push(front->left);
            q.push(front->right);
        }
        else 
        {
            cout << "# ";
        }
    }
}

int main() 
{
    int i = 0;
    BTNode* root = Create("123###45##6##", i);    
    LevelOrder(root);    //1 2 4 3 # 5 6 # # # # # # 
    cout << endl;
    return 0;
}

三、堆

  • 堆是一棵完全二叉树,顺序存储
  • 小根堆:堆中所有父节点都小于等于子节点
  • 大根堆:堆中所有父节点都大于等于子节点
  • 堆的特性可用于排序,堆排序时间复杂度为 lg(n)
#include 
#include 
#include 

#define CAPACITY 3
typedef int HData;

typedef struct HeapNode 
{
    HData* data;
    int size;
    int capacity;
}HeapNode;

void Init(HeapNode* h) 
{
    assert(h);
    h->data = (HData*)malloc(sizeof(HData) * CAPACITY);
    if (h->data == NULL) 
    {
        perror("malloc");
        exit(1);
    }
    h->size = 0;
    h->capacity = CAPACITY;
}

void Destory(HeapNode* h) 
{
    assert(h);
    free(h->data);
    h->data = NULL;
    h->size = 0;
    h->capacity = CAPACITY;
}

void Swap(HData* pData, int child, int parent) 
{
    HData tmp = pData[parent];
    pData[parent] = pData[child];
    pData[child] = tmp;
}

//向上调整
void AdjustUp(HData* pData, int child) 
{
    //小根堆
    while (child > 0) 
    {
        int parent = (child - 1) / 2;
        if (pData[child] < pData[parent]) 
        {
            Swap(pData, child, parent);
            child = parent;
        }
        else 
        {
            break;
        }
    }
}

//push元素之后,从最后一个元素向上调整
void Push(HeapNode* h, HData x) 
{
    assert(h);
    if (h->size == h->capacity) 
    {
        h->data = (HData*)realloc(h->data, sizeof(HData) * (h->size + CAPACITY));
        h->capacity += CAPACITY;
    }
    h->data[h->size] = x;
    ++h->size;
    AdjustUp(h->data, h->size - 1);
}

//向下调整
void AdjustDown(HData* pData, int size, int parent) 
{
    int child = parent * 2 + 1;
    //小根堆
    while (child < size) 
    {
        if (child + 1 < size && pData[child] > pData[child + 1]) 
            ++child;
        if (pData[child] < pData[parent]) 
        {
            Swap(pData, child, parent);
            parent = child;
            child = parent * 2 + 1;
        }
        else 
        {
            break;
        }
    }
}

//将堆顶的元素pop再向下调整
void Pop(HeapNode* h) 
{
    assert(h);
    if (h->size > 0) 
    {
        Swap(h->data, 0, h->size - 1);
        --h->size;
        AdjustDown(h->data, h->size, 0);
    }
}

HData Top(HeapNode* h) 
{
    assert(h);
    assert(h->size != 0);
    return h->data[0];
}

int main() 
{
    HeapNode h;
    Init(&h);
    int a[] = {24, 34, 34, 35, 23, 11, 12, 45, 23, 43, 64, 12};
    int i= 0;
    for (i = 0; i < sizeof(a) / sizeof(a[0]); ++i) 
        Push(&h, a[i]);
    while (h.size != 0) 
    {
        printf("%d ", Top(&h));
        Pop(&h);
    }
    printf("\n");   //利用堆进行排序
    Destory(&h);
    return 0;
}

你可能感兴趣的:(C/C++数据结构与算法,算法,数据结构,c++,c语言)