ITPub博客

首页 > 应用开发 > IT综合 > 二叉树与堆数据结构:存储原理与实现机制深度解析

二叉树与堆数据结构:存储原理与实现机制深度解析

投稿 IT综合 作者:bhluo 时间:2026-01-29 14:16:51 0 删除 编辑

《二叉树与堆数据结构:存储原理与实现机制深度解析》


二叉树和堆作为基础而重要的数据结构,在算法设计和系统开发中广泛应用。理解它们的存储原理和实现机制,是掌握高效数据处理能力的关键。


**二叉树基本概念与存储结构**


二叉树是每个节点最多有两个子节点的树形结构,包含多种特殊形式:


```cpp

// 二叉树节点定义

struct BinaryTreeNode {

    int value;

    BinaryTreeNode* left;

    BinaryTreeNode* right;

    BinaryTreeNode(int val) : value(val), left(nullptr), right(nullptr) {}

};


// 完全二叉树

class CompleteBinaryTree {

    vector<int> nodes;  // 使用数组存储完全二叉树

    

public:

    CompleteBinaryTree() {}

    

    void insert(int value) {

        nodes.push_back(value);

    }

    

    int getParentIndex(int i) {

        return (i - 1) / 2;

    }

    

    int getLeftChildIndex(int i) {

        return 2 * i + 1;

    }

    

    int getRightChildIndex(int i) {

        return 2 * i + 2;

    }

};

```


**二叉树存储实现方式**


1. **链式存储**


```cpp

class LinkedBinaryTree {

private:

    struct Node {

        int data;

        Node* left;

        Node* right;

        Node* parent;  // 可选:父节点指针

        

        Node(int val) : data(val), left(nullptr), right(nullptr), parent(nullptr) {}

    };

    

    Node* root;

    

public:

    LinkedBinaryTree() : root(nullptr) {}

    

    // 插入节点(示例:BST插入)

    void insert(int value) {

        root = insertRecursive(root, value);

    }

    

    Node* insertRecursive(Node* node, int value) {

        if (!node) {

            return new Node(value);

        }

        

        if (value < node->data) {

            node->left = insertRecursive(node->left, value);

            if (node->left) node->left->parent = node;

        } else {

            node->right = insertRecursive(node->right, value);

            if (node->right) node->right->parent = node;

        }

        

        return node;

    }

    

    // 计算树的高度

    int getHeight() const {

        return calculateHeight(root);

    }

    

private:

    int calculateHeight(Node* node) const {

        if (!node) return 0;

        return 1 + max(calculateHeight(node->left), 

                       calculateHeight(node->right));

    }

};

```


2. **顺序存储**


```cpp

class ArrayBinaryTree {

private:

    vector<int> treeArray;

    int capacity;

    

public:

    ArrayBinaryTree(int size) : capacity(size) {

        treeArray.resize(capacity, -1);  // -1表示空节点

    }

    

    // 设置节点值

    bool setNode(int index, int value) {

        if (index < 0 || index >= capacity) return false;

        treeArray[index] = value;

        return true;

    }

    

    // 获取节点值

    int getNode(int index) const {

        if (index < 0 || index >= capacity) return -1;

        return treeArray[index];

    }

    

    // 获取父节点索引

    int getParentIndex(int childIndex) const {

        if (childIndex <= 0 || childIndex >= capacity) return -1;

        return (childIndex - 1) / 2;

    }

    

    // 获取左子节点索引

    int getLeftChildIndex(int parentIndex) const {

        int leftIndex = 2 * parentIndex + 1;

        return (leftIndex < capacity) ? leftIndex : -1;

    }

    

    // 获取右子节点索引

    int getRightChildIndex(int parentIndex) const {

        int rightIndex = 2 * parentIndex + 2;

        return (rightIndex < capacity) ? rightIndex : -1;

    }

    

    // 层次遍历

    vector<int> levelOrderTraversal() const {

        vector<int> result;

        for (int i = 0; i < capacity; i++) {

            if (treeArray[i] != -1) {

                result.push_back(treeArray[i]);

            }

        }

        return result;

    }

};

```


**堆数据结构核心概念**


堆是一种特殊的完全二叉树,满足堆属性:


```cpp

enum class HeapType {

    MIN_HEAP,  // 最小堆:父节点值 <= 子节点值

    MAX_HEAP   // 最大堆:父节点值 >= 子节点值

};


class Heap {

protected:

    vector<int> heapArray;

    HeapType type;

    

public:

    Heap(HeapType heapType = HeapType::MAX_HEAP) : type(heapType) {}

    

    // 获取堆大小

    int size() const {

        return heapArray.size();

    }

    

    // 判断堆是否为空

    bool empty() const {

        return heapArray.empty();

    }

    

    // 获取堆顶元素

    int peek() const {

        if (empty()) {

            throw runtime_error("Heap is empty");

        }

        return heapArray[0];

    }

    

protected:

    // 比较函数,根据堆类型决定比较方式

    bool compare(int parent, int child) const {

        if (type == HeapType::MAX_HEAP) {

            return parent >= child;

        } else {

            return parent <= child;

        }

    }

    

    // 交换元素

    void swapElements(int i, int j) {

        swap(heapArray[i], heapArray[j]);

    }

    

    // 获取父节点索引

    int parentIndex(int i) const {

        return (i - 1) / 2;

    }

    

    // 获取左子节点索引

    int leftChildIndex(int i) const {

        return 2 * i + 1;

    }

    

    // 获取右子节点索引

    int rightChildIndex(int i) const {

        return 2 * i + 2;

    }

};

```


**最大堆实现**


```cpp

class MaxHeap : public Heap {

public:

    MaxHeap() : Heap(HeapType::MAX_HEAP) {}

    

    // 插入元素

    void push(int value) {

        heapArray.push_back(value);

        heapifyUp(heapArray.size() - 1);

    }

    

    // 移除堆顶元素

    int pop() {

        if (empty()) {

            throw runtime_error("Heap is empty");

        }

        

        int rootValue = heapArray[0];

        heapArray[0] = heapArray.back();

        heapArray.pop_back();

        

        if (!empty()) {

            heapifyDown(0);

        }

        

        return rootValue;

    }

    

    // 构建堆

    void buildHeap(const vector<int>& values) {

        heapArray = values;

        

        // 从最后一个非叶子节点开始堆化

        for (int i = parentIndex(heapArray.size() - 1); i >= 0; i--) {

            heapifyDown(i);

        }

    }

    

private:

    // 向上堆化

    void heapifyUp(int index) {

        while (index > 0) {

            int parent = parentIndex(index);

            

            if (compare(heapArray[parent], heapArray[index])) {

                break;

            }

            

            swapElements(parent, index);

            index = parent;

        }

    }

    

    // 向下堆化

    void heapifyDown(int index) {

        int size = heapArray.size();

        int largest = index;

        

        while (true) {

            int left = leftChildIndex(index);

            int right = rightChildIndex(index);

            

            if (left < size && heapArray[left] > heapArray[largest]) {

                largest = left;

            }

            

            if (right < size && heapArray[right] > heapArray[largest]) {

                largest = right;

            }

            

            if (largest == index) {

                break;

            }

            

            swapElements(index, largest);

            index = largest;

        }

    }

};

```


**最小堆实现**


```cpp

class MinHeap : public Heap {

public:

    MinHeap() : Heap(HeapType::MIN_HEAP) {}

    

    // 插入元素

    void push(int value) {

        heapArray.push_back(value);

        heapifyUp(heapArray.size() - 1);

    }

    

    // 移除堆顶元素

    int pop() {

        if (empty()) {

            throw runtime_error("Heap is empty");

        }

        

        int rootValue = heapArray[0];

        heapArray[0] = heapArray.back();

        heapArray.pop_back();

        

        if (!empty()) {

            heapifyDown(0);

        }

        

        return rootValue;

    }

    

    // 堆排序(升序)

    vector<int> heapSort() {

        vector<int> sorted;

        vector<int> original = heapArray;

        

        while (!empty()) {

            sorted.push_back(pop());

        }

        

        heapArray = original;  // 恢复原堆

        return sorted;

    }

    

private:

    // 向上堆化

    void heapifyUp(int index) {

        while (index > 0) {

            int parent = parentIndex(index);

            

            if (compare(heapArray[parent], heapArray[index])) {

                break;

            }

            

            swapElements(parent, index);

            index = parent;

        }

    }

    

    // 向下堆化

    void heapifyDown(int index) {

        int size = heapArray.size();

        int smallest = index;

        

        while (true) {

            int left = leftChildIndex(index);

            int right = rightChildIndex(index);

            

            if (left < size && heapArray[left] < heapArray[smallest]) {

<"m4.j9k5.org.cn"><"a6.j9k5.org.cn"><"d3.j9k5.org.cn">

                smallest = left;

            }

            

            if (right < size && heapArray[right] < heapArray[smallest]) {

                smallest = right;

            }

            

            if (smallest == index) {

                break;

            }

            

            swapElements(index, smallest);

            index = smallest;

        }

    }

};

```


**堆的应用场景**


1. **优先队列实现**


```cpp

template<typename T, typename Compare = less<T>>

class PriorityQueue {

private:

    vector<T> heap;

    Compare comp;

    

public:

    PriorityQueue() {}

    

    void push(const T& value) {

        heap.push_back(value);

        push_heap(heap.begin(), heap.end(), comp);

    }

    

    void pop() {

        pop_heap(heap.begin(), heap.end(), comp);

        heap.pop_back();

    }

    

    const T& top() const {

        return heap.front();

    }

    

    bool empty() const {

        return heap.empty();

    }

    

    size_t size() const {

        return heap.size();

    }

};


// 使用示例

void priorityQueueDemo() {

    PriorityQueue<int, greater<int>> minPQ;  // 最小优先队列

    PriorityQueue<int> maxPQ;               // 最大优先队列(默认)

    

    minPQ.push(10);

    minPQ.push(5);

    minPQ.push(20);

    

    cout << "Min Priority Queue top: " << minPQ.top() << endl;

    

    vector<int> tasks = {30, 10, 50, 20, 40};

    PriorityQueue<int> taskQueue;

    

    for (int task : tasks) {

        taskQueue.push(task);

    }

    

    cout << "Tasks in priority order: ";

    while (!taskQueue.empty()) {

        cout << taskQueue.top() << " ";

        taskQueue.pop();

    }

    cout << endl;

}

```


2. **堆排序算法**


```cpp

class HeapSorter {

public:

    // 原地堆排序

    void heapSort(vector<int>& arr) {

<"h7.j9k5.org.cn"><"v9.j9k5.org.cn"><"s2.j9k5.org.cn">

        int n = arr.size();

        

        // 构建最大堆

        for (int i = n / 2 - 1; i >= 0; i--) {

            heapify(arr, n, i);

        }

        

        // 逐个提取元素

        for (int i = n - 1; i > 0; i--) {

            swap(arr[0], arr[i]);

            heapify(arr, i, 0);

        }

    }

    

private:

    void heapify(vector<int>& arr, int n, int i) {

        int largest = i;

        int left = 2 * i + 1;

        int right = 2 * i + 2;

        

        if (left < n && arr[left] > arr[largest]) {

            largest = left;

        }

        

        if (right < n && arr[right] > arr[largest]) {

            largest = right;

        }

        

        if (largest != i) {

            swap(arr[i], arr[largest]);

            heapify(arr, n, largest);

        }

    }

    

public:

    // 外部堆排序(不修改原数组)

    vector<int> externalHeapSort(const vector<int>& arr) {

        MinHeap heap;

        

        // 插入所有元素

        for (int num : arr) {

            heap.push(num);

        }

        

        // 提取排序结果

        vector<int> sorted;

        while (!heap.empty()) {

            sorted.push_back(heap.pop());

        }

        

        return sorted;

    }

};

```


**二叉树与堆的存储对比**


```cpp

class StorageComparison {

public:

    struct StorageInfo {

        string name;

        size_t nodeSize;

        size_t pointerSize;

        bool sequential;

        bool dynamic;

    };

    

    static vector<StorageInfo> getComparison() {

        return {

            {"链式二叉树", sizeof(int), sizeof(void*)*2, false, true},

            {"数组二叉树", sizeof(int), 0, true, false},

            {"二叉堆", sizeof(int), 0, true, true},

            {"左倾堆", sizeof(int), sizeof(void*)*2, false, true}

        };

    }

    

    static void analyzeMemoryUsage(int nodeCount) {

        cout << "节点数: " << nodeCount << endl;

        cout << "=" << 40 << endl;

        

        auto comparisons = getComparison();

        

        for (const auto& info : comparisons) {

            size_t totalMemory = nodeCount * info.nodeSize;

            

            if (!info.sequential) {

                totalMemory += nodeCount * info.pointerSize * 2;

            }

            

            cout << info.name << ": " 

                 << totalMemory / 1024.0 << " KB" << endl;

        }

    }

};

```


**高级堆结构**


1. **二项堆**


```cpp

class BinomialHeapNode {

public:

    int value;

    int degree;

    BinomialHeapNode* child;

    BinomialHeapNode* sibling;

    BinomialHeapNode* parent;

    

    BinomialHeapNode(int val) : value(val), degree(0), 

                               child(nullptr), sibling(nullptr), 

                               parent(nullptr) {}

};


class BinomialHeap {

private:

    BinomialHeapNode* head;

    

    // 合并两个二项树

    BinomialHeapNode* mergeTrees(BinomialHeapNode* a, BinomialHeapNode* b) {

        if (a->value > b->value) {

            swap(a, b);

        }

        

        b->parent = a;

        b->sibling = a->child;

        a->child = b;

        a->degree++;

        

        return a;

    }

    

    // 合并两个堆

    BinomialHeapNode* mergeHeaps(BinomialHeapNode* h1, BinomialHeapNode* h2) {

        if (!h1) return h2;

        if (!h2) return h1;

        

        BinomialHeapNode* result = nullptr;

        BinomialHeapNode* current = nullptr;

        

        // 按度数合并

        while (h1 && h2) {

            BinomialHeapNode* temp;

            

            if (h1->degree <= h2->degree) {

                temp = h1;

                h1 = h1->sibling;

            } else {

                temp = h2;

                h2 = h2->sibling;

            }

            

            if (!result) {

                result = temp;

                current = temp;

            } else {

                current->sibling = temp;

                current = temp;

            }

        }

        

        if (h1) current->sibling = h1;

        if (h2) current->sibling = h2;

        

        return result;

    }

    

public:

    BinomialHeap() : head(nullptr) {}

    

    void insert(int value) {

        BinomialHeapNode* newNode = new BinomialHeapNode(value);

        head = mergeHeaps(head, newNode);

    }

    

    int getMin() {

        if (!head) throw runtime_error("Heap is empty");

        

        BinomialHeapNode* minNode = head;

        BinomialHeapNode* current = head->sibling;

        

        while (current) {

            if (current->value < minNode->value) {

                minNode = current;

            }

            current = current->sibling;

        }

        

        return minNode->value;

    }

};

```


**应用实例:任务调度系统**


```cpp

class TaskScheduler {

private:

    struct Task {

        int id;

        int priority;      // 优先级,值越小优先级越高

        string description;

        time_t deadline;   // 截止时间

        

        bool operator<(const Task& other) const {

            if (priority != other.priority) {

                return priority > other.priority;  // 最小堆比较

            }

            return deadline > other.deadline;

        }

    };

    

    MinHeap taskHeap;

    unordered_map<int, Task> taskMap;

    

public:

    void addTask(int id, int priority, const string& desc, time_t deadline) {

        Task task{id, priority, desc, deadline};

        taskHeap.push(priority * 1000 + id);  // 简单哈希,实际需要存储Task对象

        taskMap[id] = task;

    }

    

    Task getNextTask() {

        if (taskHeap.empty()) {

            throw runtime_error("No tasks available");

        }

        

        int key = taskHeap.peek();

        taskHeap.pop();

        

        int id = key % 1000;

        return taskMap[id];

    }

    

    void displayAllTasks() {

        cout << "Current Tasks:" << endl;

        cout << "ID\tPriority\tDescription\tDeadline" << endl;

        

        // 注意:这里需要复制堆来遍历

        MinHeap tempHeap = taskHeap;

        

        while (!tempHeap.empty()) {

            int key = tempHeap.peek();

            tempHeap.pop();

            

            int id = key % 1000;

            Task task = taskMap[id];

            

            cout << task.id << "\t" << task.priority << "\t\t"

                 << task.description << "\t"

                 << ctime(&task.deadline);

        }

    }

};

```


**性能分析与优化**


```cpp

class PerformanceAnalyzer {

public:

    static void benchmarkOperations(int operationCount) {

        cout << "操作次数: " << operationCount << endl;

        cout << "=" << 40 << endl;

        

        // 测试插入性能

        auto start = chrono::high_resolution_clock::now();

        

        MaxHeap heap;

        for (int i = 0; i < operationCount; i++) {

            heap.push(i);

        }

        

        auto end = chrono::high_resolution_clock::now();

        auto insertTime = chrono::duration_cast<chrono::milliseconds>(end - start);

        

        // 测试删除性能

        start = chrono::high_resolution_clock::now();

        

        while (!heap.empty()) {

            heap.pop();

        }

        

        end = chrono::high_resolution_clock::now();

        auto deleteTime = chrono::duration_cast<chrono::milliseconds>(end - start);

        

        cout << "插入时间: " << insertTime.count() << "ms" << endl;

        cout << "删除时间: " << deleteTime.count() << "ms" << endl;

        

        // 分析时间复杂度

        cout << "\n时间复杂度分析:" << endl;

        cout << "插入操作: O(log n)" << endl;

        cout << "删除操作: O(log n)" << endl;

        cout << "获取堆顶: O(1)" << endl;

    }

    

    static void compareWithBinaryTree(int dataSize) {

        vector<int> data(dataSize);

        iota(data.begin(), data.end(), 1);

        random_shuffle(data.begin(), data.end());

        

        // 二叉搜索树插入

        auto start = chrono::high_resolution_clock::now();

        BinarySearchTree bst;

        for (int num : data) {

            bst.insert(num);

        }

        auto end = chrono::high_resolution_clock::now();

        auto bstTime = chrono::duration_cast<chrono::milliseconds>(end - start);

        

        // 堆插入

        start = chrono::high_resolution_clock::now();

        MaxHeap heap;

        for (int num : data) {

            heap.push(num);

        }

        end = chrono::high_resolution_clock::now();

        auto heapTime = chrono::duration_cast<chrono::milliseconds>(end - start);

        

        cout << "数据规模: " << dataSize << endl;

        cout << "BST插入时间: " << bstTime.count() << "ms" << endl;

        cout << "堆插入时间: " << heapTime.count() << "ms" << endl;

    }

};

```


**总结与选择指南**


二叉树和堆各有适用场景,选择时需考虑:


1. **二叉树适用场景**:

   - 需要保持数据有序性(BST)

   - 需要支持多种遍历方式

   - 数据动态性强,频繁插入删除


2. **堆适用场景**:

   - 需要快速获取最大/最小值

   - 实现优先队列

   - 堆排序和Top-K问题


3. **存储选择原则**:

   - 完全二叉树适合数组存储,节省空间

   - 普通二叉树适合链式存储,灵活性高

   - 堆必须使用数组存储,保证完全二叉树特性


4. **性能权衡**:

   - 堆的插入删除平均O(log n)

   - BST在平衡情况下O(log n),退化情况O(n)

   - 数组存储缓存友好,链式存储动态性好


理解二叉树和堆的存储原理与实现机制,能够帮助开发者在不同场景下选择最合适的数据结构,优化算法性能。这两种基础结构相辅相成,构成了更复杂数据结构的基础。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/19545/viewspace-3109381/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2015-11-01

  • 博文量
    895
  • 访问量
    934212