为了账号安全,请及时绑定邮箱和手机立即绑定

算法与数据结构入门:轻松掌握编程基础

标签:
杂七杂八
概述

算法与数据结构入门是编程领域基石,本文旨在为初学者提供基础指南,覆盖从数组、链表、栈与队列,到排序算法的讲解,并深入探讨树结构和图论基础,通过实践案例如最小生成树,帮助读者掌握高效解决问题的核心技能。通过实践、阅读与深入学习,构建扎实的编程基础,迈向高效编程之路。

引言

在编程世界里,算法与数据结构是构建高效且智能软件的核心基石。它们不仅决定着程序的运行效率,还影响着代码的可维护性和可扩展性。对于初学者而言,理解算法与数据结构的概念,熟悉常见的数据结构和算法,是迈向编程世界大门的关键一步。本文旨在提供一个简洁、教育性的指南,帮助初学者轻松掌握算法与数据结构的基础知识,并通过实践案例加深理解。

数据结构基础
数组

数据结构是计算机存储和管理数据的方式。数组是一种最基础的数据结构,用于存储多个相同类型的数据元素。在不同编程语言中,数组的实现方式可能有所不同,但基本操作包括:

  • 定义int arr[5] 创建一个包含5个整数的数组。
  • 访问元素int value = arr[0]; 访问数组的第一个元素。
  • 遍历和修改:遍历数组并执行操作是数组使用中的重要部分。

```c++

include <iostream>

int main() {
int nums[5] = {1, 2, 3, 4, 5};
for(int i = 0; i < 5; i++) {
std::cout << "Element " << i << ": " << nums[i] << std::endl;
}
return 0;
}


## 链表

链表是一种动态数据结构,每个元素(节点)包含两部分:数据和指向下一个节点的链接。

### 单链表

- **单链表示例**
```c++
struct Node {
    int data;
    Node* next;
};

void printList(Node* head) {
    Node* current = head;
    while(current != nullptr) {
        std::cout << current->data << " ";
        current = current->next;
    }
    std::cout << std::endl;
}

int main() {
    Node* head = new Node{1, nullptr};
    head->next = new Node{2, nullptr};
    head->next->next = new Node{3, nullptr};

    printList(head);
    return 0;
}

循环链表

```c++
struct Node {
int data;
Node* next;
};

void createLoop(Node head) {
Node
end = head;
while(end->next != nullptr)
end = end->next;
end->next = head;
}

void printList(Node head) {
Node
current = head;
do {
std::cout << current->data << " ";
current = current->next;
} while(current != head);
std::cout << std::endl;
}

int main() {
Node* head = new Node{1, nullptr};
head->next = new Node{2, nullptr};
head->next->next = new Node{3, nullptr};

createLoop(head);

printList(head);
return 0;

}


## 栈与队列

栈和队列是两种特殊的线性数据结构:

- **栈**(后进先出):元素只能从顶部插入或删除。
- **队列**(先进先出):元素从一端插入,从另一端删除。

### 实现栈与队列

```c++
#include <iostream>
#include <stack>
#include <queue>

int main() {
    std::stack<int> stack;
    stack.push(1);
    stack.push(2);
    stack.push(3);
    std::cout << "Stack: ";
    while(!stack.empty()) {
        std::cout << stack.top() << " ";
        stack.pop();
    }
    std::cout << std::endl;

    std::queue<int> queue;
    queue.push(1);
    queue.push(2);
    queue.push(3);
    std::cout << "Queue: ";
    while(!queue.empty()) {
        std::cout << queue.front() << " ";
        queue.pop();
    }
    std::cout << std::endl;
    return 0;
}
算法基础概念

算法是解决问题的步骤集,具有明确的开始和结束,且满足以下特性:

  • 输入:算法有零个或多个输入。
  • 输出:至少一个输出。
  • 确定性:算法的每一步都是清晰明确的,无歧义。
  • 有效性:算法的每一步都可以在有限时间内完成。

时间复杂度与空间复杂度

  • 时间复杂度:描述执行算法所需的时间与问题规模(通常以输入数据的大小为度量)之间的关系。
  • 空间复杂度:描述执行算法所需内存(空间)与输入数据大小之间的关系。

排序算法

排序是常见的算法任务之一,用于将数据按照特定顺序排列。

  • 冒泡排序:通过重复遍历列表,比较相邻元素并交换位置,使得较大的元素逐渐移到列表的末尾。
  • 插入排序:将元素插入已排序的部分,保持整体的有序性。
  • 选择排序:每次从未排序部分选取最小元素,与当前未排序部分的第一个元素交换位置。

```c++
void bubbleSort(int arr[], int n) {
for(int i = 0; i < n-1; i++) {
for(int j = 0; j < n-i-1; j++) {
if(arr[j] > arr[j+1]) {
std::swap(arr[j], arr[j+1]);
}
}
}
}

void insertSort(int arr[], int n) {
for(int i = 1; i < n; i++) {
int key = arr[i];
int j = i-1;
while(j >= 0 && arr[j] > key) {
arr[j+1] = arr[j];
j = j-1;
}
arr[j+1] = key;
}
}

void selectionSort(int arr[], int n) {
for(int i = 0; i < n-1; i++) {
int minIndex = i;
for(int j = i+1; j < n; j++) {
if(arr[j] < arr[minIndex]) {
minIndex = j;
}
}
std::swap(arr[i], arr[minIndex]);
}
}


# 常用数据结构与算法应用

## 树结构

树是一种分层的数据结构,每个节点最多有多个子节点(子树)。

- **二叉树**:每个节点最多有两个子节点。
- **平衡树**:
  - **AVL树**:动态平衡,确保树的高度差不超过1。
  - **红黑树**:通过颜色标记维护平衡,保证查找、插入、删除操作的效率。

### 实践案例:最小生成树

最小生成树算法如克鲁斯卡尔算法,用于在无向、连通图中查找最小的生成树。

```c++
#include <iostream>
#include <vector>
#include <utility> // For std::pair

struct Edge {
    int src, dest, weight;
};

class Graph {
    int V;
    std::vector<Edge> *adj;
    void printMST(std::vector<Edge> MST[]);
    void KruskalMST();
    bool compare(const Edge& e1, const Edge& e2);
public:
    Graph(int V);
    void addEdge(int u, int v, int w);
    void MST();
};

Graph::Graph(int V) {
    this->V = V;
    adj = new std::vector<Edge>[V];
}

void Graph::addEdge(int u, int v, int w) {
    Edge edge = {u, v, w};
    adj[u].push_back(edge);
}

void Graph::MST() {
    std::vector<Edge> MST;
    KruskalMST();
    printMST(MST);
}

void Graph::KruskalMST() {
    std::sort(adj[0].begin(), adj[0].end(), compare);
    int parent[V];
    int i = 0;
    for (int i = 0; i < V; ++i) {
        parent[i] = i;
    }
    while (MST.size() < V - 1) {
        edge e = adj[0][i];
        i++;
        int u = e.src;
        int v = e.dest;
        int x = find(parent, u);
        int y = find(parent, v);
        if (x != y) {
            parent[x] = y;
            MST.push_back(e);
            std::cout << u << " -- " << v << std::endl;
        }
    }
}

int find(int parent[], int i) {
    if (parent[i] == i) {
        return i;
    }
    return find(parent, parent[i]);
}

bool Graph::compare(const Edge& e1, const Edge& e2) {
    return e1.weight < e2.weight;
}

void Graph::printMST(std::vector<Edge> MST[]) {
    std::cout << "Edges of Minimum Spanning Tree are:\n";
    for (Edge e : MST) {
        std::cout << e.src << " -- " << e.dest << " = " << e.weight << std::endl;
    }
}

int main() {
    Graph g(5);
    g.addEdge(0, 1, 10);
    g.addEdge(0, 4, 5);
    g.addEdge(1, 2, 3);
    g.addEdge(1, 4, 2);
    g.addEdge(2, 3, 7);
    g.addEdge(3, 4, 9);
    g.MST();
    return 0;
}
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消