【透过 C++ 实现数据结构:链表、数组、树和图蕴含的逻辑深度解析】

news/2025/2/24 18:46:49

一、数组 (Array) 实现

1. 基础数组

#include <iostream>
using namespace std;

int main() {
    // 静态数组
    int staticArr[5] = {1,2,3,4,5};
    
    // 动态数组
    int size = 5;
    int* dynamicArr = new int[size];
    
    // 访问元素
    cout << "Third element: " << dynamicArr[2] << endl;
    
    delete[] dynamicArr; // 释放内存
    return 0;
}

2. 动态扩容数组(类似vector)

class DynamicArray {
private:
    int* arr;
    int capacity;
    int length;
    
public:
    DynamicArray() : capacity(2), length(0) {
        arr = new int[capacity];
    }

    void push_back(int val) {
        if(length == capacity) {
            // 扩容策略
            capacity *= 2;
            int* newArr = new int[capacity];
            for(int i=0; i<length; i++) {
                newArr[i] = arr[i];
            }
            delete[] arr;
            arr = newArr;
        }
        arr[length++] = val;
    }

    int at(int index) {
        if(index >= length) throw out_of_range("Index out of range");
        return arr[index];
    }

    ~DynamicArray() {
        delete[] arr;
    }
};

二、链表 (Linked List)

1. 单链表实现

class ListNode {
public:
    int val;
    ListNode* next;
    ListNode(int x) : val(x), next(nullptr) {}
};

class LinkedList {
private:
    ListNode* head;
public:
    LinkedList() : head(nullptr) {}

    // 添加节点到头部
    void addFront(int val) {
        ListNode* newNode = new ListNode(val);
        newNode->next = head;
        head = newNode;
    }

    // 删除节点
    void deleteNode(int val) {
        ListNode* prev = nullptr;
        ListNode* curr = head;
        
        while(curr) {
            if(curr->val == val) {
                if(prev) {
                    prev->next = curr->next;
                } else {
                    head = curr->next;
                }
                delete curr;
                return;
            }
            prev = curr;
            curr = curr->next;
        }
    }

    // 遍历打印
    void print() {
        ListNode* curr = head;
        while(curr) {
            cout << curr->val << " -> ";
            curr = curr->next;
        }
        cout << "null" << endl;
    }
};

2. 双链表实现

class DListNode {
public:
    int val;
    DListNode *prev, *next;
    DListNode(int x) : val(x), prev(nullptr), next(nullptr) {}
};

class DoublyLinkedList {
private:
    DListNode* head;
    DListNode* tail;
public:
    // 添加节点到尾部
    void addBack(int val) {
        DListNode* newNode = new DListNode(val);
        if(!head) {
            head = tail = newNode;
        } else {
            tail->next = newNode;
            newNode->prev = tail;
            tail = newNode;
        }
    }
    
    // 其他操作类似单链表,需要处理prev指针
};

三、树 (Tree)

1. 二叉树实现

class TreeNode {
public:
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

class BinaryTree {
private:
    TreeNode* root;

    // 递归插入
    TreeNode* insert(TreeNode* node, int val) {
        if(!node) return new TreeNode(val);
        
        if(val < node->val) {
            node->left = insert(node->left, val);
        } else {
            node->right = insert(node->right, val);
        }
        return node;
    }

public:
    BinaryTree() : root(nullptr) {}

    void insert(int val) {
        root = insert(root, val);
    }

    // 前序遍历
    void preOrder(TreeNode* node) {
        if(node) {
            cout << node->val << " ";
            preOrder(node->left);
            preOrder(node->right);
        }
    }
    
    // 其他遍历方式类似
};

2. AVL树(平衡二叉搜索树)

class AVLNode {
public:
    int val;
    AVLNode *left, *right;
    int height;
    AVLNode(int x) : val(x), left(nullptr), right(nullptr), height(1) {}
};

class AVLTree {
private:
    AVLNode* root;
    
    int getHeight(AVLNode* node) {
        return node ? node->height : 0;
    }
    
    // 右旋转
    AVLNode* rightRotate(AVLNode* y) {
        AVLNode* x = y->left;
        AVLNode* T2 = x->right;

        x->right = y;
        y->left = T2;

        y->height = max(getHeight(y->left), getHeight(y->right)) + 1;
        x->height = max(getHeight(x->left), getHeight(x->right)) + 1;

        return x;
    }
    
    // 其他旋转操作和平衡因子计算...
};

四、图 (Graph)

1. 邻接矩阵表示法

class GraphMatrix {
private:
    int V; // 顶点数
    vector<vector<int>> adj;

public:
    GraphMatrix(int vertices) : V(vertices) {
        adj = vector<vector<int>>(V, vector<int>(V, 0));
    }

    void addEdge(int u, int v) {
        adj[u][v] = 1;
        adj[v][u] = 1; // 无向图
    }
};

2. 邻接表表示法(更高效)

class GraphList {
private:
    int V;
    vector<list<int>> adj;

public:
    GraphList(int vertices) : V(vertices), adj(vertices) {}

    void addEdge(int u, int v) {
        adj[u].push_back(v);
        adj[v].push_back(u); // 无向图
    }

    // BFS遍历
    void BFS(int start) {
        vector<bool> visited(V, false);
        queue<int> q;
        
        visited[start] = true;
        q.push(start);

        while(!q.empty()) {
            int u = q.front();
            q.pop();
            cout << u << " ";

            for(int v : adj[u]) {
                if(!visited[v]) {
                    visited[v] = true;
                    q.push(v);
                }
            }
        }
    }
};

关键点解析:

  1. 内存管理

    • 使用new/delete管理堆内存
    • 链表节点要及时释放内存
    • 推荐使用智能指针(如unique_ptr
  2. 时间复杂度

    • 数组随机访问:O(1)
    • 链表插入/删除:O(1)(已知位置)
    • 二叉树平衡操作:O(log n)
  3. 设计模式

    • 使用类封装数据结构
    • 分离节点类和容器类
    • 实现迭代器模式遍历元素
  4. 扩展功能

    • 实现STL风格的接口(begin/end)
    • 添加异常处理
    • 支持模板泛型编程

建议按照以下顺序练习:

  1. 先实现数组和链表
  2. 再实现二叉树及其遍历
  3. 最后实现图结构及算法(DFS/BFS)
  4. 尝试实现更复杂的结构(红黑树、哈希表)

注意:实际开发中应优先使用STL容器(vector、list、map等),这些实现主要用于学习原理。


http://www.niftyadmin.cn/n/5864714.html

相关文章

全面汇总windows进程通信(二)

在Windows操作系统下,实现进程间通信(IPC, Inter-Process Communication)有几种常见的方法,包括使用管道(Pipe)、共享内存(Shared Memory)、消息队列(Message Queue)、命名管道(Named Pipe)、套接字(Socket)等。本文介绍如下几种: 信号量(Semaphore)和互斥量(…

详细介绍STM32(32位单片机)外设应用

以下是关于STM32外设应用的详细介绍&#xff0c;结合其功能特点及实际应用场景进行分类说明&#xff1a; 一、基本接口与数字外设 GPIO&#xff08;通用输入输出端口&#xff09; 功能&#xff1a;支持输入/输出模式切换&#xff0c;可配置为推挽、开漏、上拉/下拉等模式&#…

C#上位机--循环语句

序言 在 C# 编程中&#xff0c;循环语句是非常重要的控制结构&#xff0c;它允许我们重复执行一段代码&#xff0c;直到满足特定的条件。通过使用循环&#xff0c;我们可以高效地处理大量数据&#xff0c;简化代码逻辑。本文将详细介绍 C# 中四种常见的循环语句&#xff1a;Fo…

SCSS——CSS的扩展和进化

一、SCSS是什么&#xff1f; SCSS&#xff08;Sassy CSS&#xff09; 就相当于CSS&#xff08;层叠样式表&#xff09;突然获得了编程语言的力量——可以写变量、玩函数、拆模块&#xff0c;甚至是“继承”样式&#xff01;实际上&#xff0c;SCSS就是一个让前端开发者效率飙升…

Java+SpringBoot+Vue+数据可视化的在线教育课程管理网站

感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。 背景介绍 在信息时代的浪潮下&#xff0c;互联网技术以前所未有的速度迅猛发展&#xff0c;深刻地…

Spring Boot数据访问(JDBC)全解析:从基础配置到高级调优

文章目录 引言一、Spring Boot JDBC核心架构1.1 核心组件关系图1.2 自动配置逻辑 二、基础配置实践2.1 数据源配置2.2 多数据源配置 三、JdbcTemplate深度使用3.1 基础CRUD操作3.2 批处理优化 四、事务管理4.1 声明式事务4.2 事务传播机制 五、异常处理5.1 Spring异常体系5.2 自…

Windows11安装GPU版本Pytorch2.6教程

1: 准备工作 针对已经安装好的Windows11系统&#xff0c;先检查Nvidia驱动和使用的CUDA版本情况。先打开Windows PowerShell&#xff0c;通过nvidia-smi命令查看GPU的情况&#xff0c;结果如下图1所示&#xff0c;从结果中可知使用的CUDA版本为12.8。 图1&#xff1a;检测安装…

LLM2CLIP论文学习笔记:强大的语言模型解锁更丰富的视觉表征

1. 写在前面 今天分享的一篇论文《LLM2CLIP: P OWERFUL L ANGUAGE M ODEL U NLOCKS R ICHER V ISUAL R EPRESENTATION》&#xff0c; 2024年9月微软和同济大学的一篇paper&#xff0c; 是多模态领域的一篇工作&#xff0c;主要探索了如何将大模型融合到Clip模型里面来进一步提…