「C++系列」数据结构

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站:人工智能教程

一、数据结构

C++作为一种高效的编程语言,提供了丰富的内置数据类型和库,支持各种复杂的数据结构实现。C++中的数据结构主要分为线性数据结构和非线性数据结构两大类,每种数据结构都有其独特的特点和应用场景。

1. 线性数据结构

线性数据结构中的数据元素之间存在一对一的线性关系。常见的C++线性数据结构包括:

  1. 数组(Array)
  • 定义:数组是一种聚合数据类型,用于存储相同类型的元素集合。
  • 特点:通过索引访问元素,访问速度快(O(1)),但插入和删除操作(尤其是中间位置)可能较慢。数组分为静态数组和动态数组,静态数组在编译时确定大小,不能动态调整;动态数组在运行时分配内存,可以动态调整大小(如使用newdelete操作符,或在C++11及以后版本中使用std::vector)。
  1. 链表(Linked List)
  • 定义:链表是一种动态数据结构,由一系列节点组成,每个节点包含数据和指向下一个节点的指针。
  • 特点:插入和删除操作(尤其是中间位置)速度快(O(1)),但访问元素可能较慢(需要遍历链表)。链表分为单向链表、双向链表和循环链表等。
  1. 栈(Stack)
  • 定义:栈是一种后进先出(LIFO)的数据结构。
  • 特点:主要操作包括push(压栈,添加元素到栈顶)、pop(弹栈,移除栈顶元素)和peek(查看栈顶元素)。栈可以使用数组或链表来实现,C++标准模板库(STL)提供了std::stack容器。
  1. 队列(Queue)
  • 定义:队列是一种先进先出(FIFO)的数据结构。
  • 特点:主要操作包括enqueue(入队,添加元素到队尾)、dequeue(出队,移除队头元素)和front/back(查看队头/队尾元素)。队列也可以使用数组或链表来实现,C++ STL提供了std::queue容器。

2. 非线性数据结构

非线性数据结构中的数据元素之间存在一对多或多对多的关系。常见的C++非线性数据结构包括:

  1. 树(Tree)
  • 定义:树是一种层次化的数据结构,由节点组成,每个节点有零个或多个子节点。
  • 特点:节点之间的关系是层次和分支的,如二叉树、平衡二叉树、红黑树等。树结构常用于实现排序、搜索和存储层次数据。
  1. 图(Graph)
  • 定义:图由节点(或顶点)和边组成,用于表示复杂的关系网络。
  • 特点:节点之间的关系是多对多的,常用于表示社交网络、地图等。图分为无向图和有向图,图的表示方法有邻接矩阵和邻接表等。
  1. 哈希表(Hash Table)
  • 定义:哈希表是一种通过哈希函数将键映射到存储位置的数据结构。
  • 特点:访问速度快(平均时间复杂度为O(1)),常用于实现快速查找、插入和删除操作。
  1. 堆(Heap)
  • 定义:堆是一种特殊的树形数据结构,满足堆属性(父节点的值大于或等于(最大堆)或小于或等于(最小堆)其子节点的值)。
  • 特点:常用于实现优先队列,如操作系统的任务调度等。C++ STL提供了std::priority_queue容器,它底层通常使用最大堆实现。

3. 其他重要数据结构

  • 字符串(String):虽然字符串通常不被视为一种独立的数据结构,但在C++中,字符串是一个非常重要的数据类型,常用于表示文本数据。C++标准库提供了std::string类来管理字符串。

二、定义数据结构

在C++中,数据结构是通过类(class)或结构体(struct)来定义的,这些结构包含了数据成员(即属性)和成员函数(即方法),用于操作这些数据。下面我将给出几种常见数据结构的定义及简单案例。

1. 数组(Array)

虽然数组不是通过类或结构体显式定义的,但它是C++中最基本的数据结构之一。不过,为了展示自定义数据结构的思路,我们可以考虑一个封装了动态数组的类(类似于std::vector的简化版)。

#include <iostream>

class DynamicArray {
private:
    int* arr;
    int capacity;
    int size;

public:
    DynamicArray(int capacity = 10) : capacity(capacity), size(0), arr(new int[capacity]) {}

    ~DynamicArray() {
        delete[] arr;
    }

    void add(int element) {
        if (size == capacity) {
            // 简化处理,实际应更复杂地处理扩容
            capacity *= 2;
            int* newArr = new int[capacity];
            for (int i = 0; i < size; ++i) {
                newArr[i] = arr[i];
            }
            delete[] arr;
            arr = newArr;
        }
        arr[size++] = element;
    }

    void print() {
        for (int i = 0; i < size; ++i) {
            std::cout << arr[i] << " ";
        }
        std::cout << std::endl;
    }
};

int main() {
    DynamicArray myArray;
    myArray.add(1);
    myArray.add(2);
    myArray.add(3);
    myArray.print(); // 输出: 1 2 3
    return 0;
}

2. 链表(LinkedList)

链表是一种动态数据结构,节点包含数据和指向下一个节点的指针。

#include <iostream>

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

class LinkedList {
private:
    ListNode* head;

public:
    LinkedList() : head(nullptr) {}

    void append(int val) {
        ListNode* newNode = new ListNode(val);
        if (!head) {
            head = newNode;
        } else {
            ListNode* current = head;
            while (current->next) {
                current = current->next;
            }
            current->next = newNode;
        }
    }

    void print() {
        ListNode* current = head;
        while (current) {
            std::cout << current->val << " ";
            current = current->next;
        }
        std::cout << std::endl;
    }

    ~LinkedList() {
        // 简化处理,实际应递归删除所有节点
        while (head) {
            ListNode* temp = head;
            head = head->next;
            delete temp;
        }
    }
};

int main() {
    LinkedList myList;
    myList.append(1);
    myList.append(2);
    myList.append(3);
    myList.print(); // 输出: 1 2 3
    return 0;
}

3. 栈(Stack)

栈是一种后进先出(LIFO)的数据结构,可以使用数组或链表实现。

#include <iostream>
#include <vector>

class Stack {
private:
    std::vector<int> elements;

public:
    void push(int val) {
        elements.push_back(val);
    }

    int pop() {
        if (elements.empty()) {
            throw std::out_of_range("Stack is empty!");
        }
        int top = elements.back();
        elements.pop_back();
        return top;
    }

    int top() {
        if (elements.empty()) {
            throw std::out_of_range("Stack is empty!");
        }
        return elements.back();
    }

    bool empty() {
        return elements.empty();
    }
};

int main() {
    Stack myStack;
    myStack.push(1);
}

三、指针、关键字

在C++中,数据结构和指针、关键字是紧密相关的概念。指针是C++中一个非常强大的特性,它允许程序直接访问和操作内存地址。而关键字则是C++语言预留的、具有特殊含义的单词,它们不能被用作变量名、函数名等标识符。下面我将分别解释指针在数据结构中的应用,以及几个与数据结构紧密相关的C++关键字。

1. 指针

指针在数据结构中扮演着至关重要的角色。它们允许我们动态地创建和操作数据结构,如链表、树和图等。通过使用指针,我们可以构建出复杂的数据结构,这些结构能够高效地存储和访问数据。

链表

在链表中,每个节点都包含数据和指向下一个节点的指针。这些指针允许我们遍历链表,并在需要时插入或删除节点。

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

在树中,每个节点通常包含数据和指向其子节点的指针。这些指针允许我们访问树中的任意节点,并执行诸如搜索、插入和删除等操作。

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

2. 关键字

  1. classstruct

classstruct 关键字用于定义类。在C++中,类和结构体非常相似,但默认情况下,类的成员是私有的(private),而结构体的成员是公共的(public)。然而,这种差异可以通过显式指定成员访问修饰符来覆盖。类和结构体都可用于定义复杂的数据结构。

  1. newdelete

newdelete 关键字用于在堆上动态地分配和释放内存。这对于创建需要动态大小的数据结构(如动态数组、链表等)非常有用。

  1. privateprotectedpublic

这些关键字用于指定类成员的访问级别。在定义类时,它们决定了哪些成员可以从类的外部访问。这对于封装和隐藏数据结构的内部实现细节非常重要。

  1. static

static 关键字在类中有多种用途,包括声明静态成员变量和静态成员函数。静态成员变量在类的所有对象之间共享,而静态成员函数则不能直接访问类的非静态成员。

  1. template

template 关键字用于定义模板类、模板函数等。模板是C++泛型编程的基础,允许我们编写与类型无关的代码。这对于创建可重用且类型安全的数据结构非常有用。

  1. typename

typename 关键字用于在模板定义中指示紧随其后的标识符是一个类型。这在模板编程中尤其有用,因为它可以帮助编译器区分类型名和变量名。
在这里插入图片描述

四、相关链接

  1. Visual Studio Code下载地址
  2. Sublime Text下载地址
  3. 「C++系列」C++简介、应用领域
  4. 「C++系列」C++ 基本语法
  5. 「C++系列」C++ 数据类型
  6. 「C++系列」C++ 变量类型
  7. 「C++系列」C++ 变量作用域
  8. 「C++系列」C++ 常量知识点-细致讲解
  9. 「C++系列」C++ 修饰符类型
  10. 「C++系列」一篇文章说透【存储类】
  11. 「C++系列」一篇文章讲透【运算符】
  12. 「C++系列」循环
  13. 「C++系列」判断
  14. 「C++系列」函数/内置函数
  15. 「C++系列」数字/随机数
  16. 「C++系列」数组
  17. 「C++系列」字符串
  18. 「C++系列」指针
  19. 「C++系列」引用
  20. 「C++系列」日期/时间
  21. 「C++系列」输入/输出
  • 43
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 16
    评论
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

·零落·

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值