【CSP考点总结】(3)

十一、二维矩阵的Z字扫描

void zScan(vector<vector<int>>& M, vector<int>& m) {
    int size = 8; // 矩阵大小为8x8
    vector<int> result;
    int i = 0, j = 0, mi = 0;
    bool up = true; // 用于标识当前移动方向,初始为向上

    for (int k = 0; k < size * size; ++k) {
        if (mi < m.size())
        {
            M[i][j] = m[mi];
            mi++;
        }
        else M[i][j] = 0;

        if (up) { // 如果当前方向是向上
            if (j == size - 1) { // 如果触及右边界
                ++i; // 向下移动
                up = false; // 改变方向
            }
            else if (i == 0) { // 如果触及上边界
                ++j; // 向右移动
                up = false; // 改变方向
            }
            else { // 否则,继续向上和向右移动
                --i;
                ++j;
            }
        }
        else { // 如果当前方向是向下
            if (i == size - 1) { // 如果触及底边界
                ++j; // 向右移动
                up = true; // 改变方向
            }
            else if (j == 0) { // 如果触及左边界
                ++i; // 向下移动
                up = true; // 改变方向
            }
            else { // 否则,继续向下和向左移动
                ++i;
                --j;
            }
        }
    }
}

十二、快速排序

void quickSort(int arr[], int left, int right) {
    if (left < right) {
        int pivot = partition(arr, left, right); // 执行分区操作,找到基准元素的正确位置
        quickSort(arr, left, pivot - 1);  // 递归对基准元素左侧的元素进行快速排序
        quickSort(arr, pivot + 1, right); // 递归对基准元素右侧的元素进行快速排序
    }
}

int partition(int arr[], int left, int right) { // 分区函数
    int pivot = arr[right];  // 选择最右侧的元素作为基准元素
    int i = left - 1;  // i指针用于跟踪比基准小的元素的最后位置
    for (int j = left; j < right; j++) {
        // 如果当前元素小于或等于基准元素
        if (arr[j] <= pivot) {
            i++;    // 移动i指针
            swap(arr[i], arr[j]); // 交换元素,将较小的元素移至左侧
        }
    }
    swap(arr[i + 1], arr[right]); // 将基准元素移至正确的位置
    return i + 1; // 返回基准元素的位置
}

int main() {
    int arr[] = {10, 7, 8, 9, 1, 5};
    int n = sizeof(arr) / sizeof(arr[0]);
    quickSort(arr, 0, n - 1); // 对数组进行快速排序
    cout << "排序后的数组: ";
    for (int i = 0; i < n; i++)
        cout << arr[i] << " ";
    return 0;
}

十三、DFS/BFS

struct TreeNode {
    int value;           // 节点存储的值
    TreeNode *left;      // 指向左子节点的指针
    TreeNode *right;     // 指向右子节点的指针
    TreeNode(int val) : value(val), left(nullptr), right(nullptr) {}
};

void depthFirstSearch(TreeNode* node) { // 深度优先搜索函数
    if (node == nullptr) return; // 如果节点为空,则返回
    cout << node->value << " "; // 处理当前节点,例如打印节点值
    depthFirstSearch(node->left); // 递归搜索左子树
    depthFirstSearch(node->right); // 递归搜索右子树
}

void breadthFirstSearch(TreeNode* root) { // 广度优先搜索函数
    if (root == nullptr) return; // 如果树为空,则直接返回
    queue<TreeNode*> q; // 定义一个队列,用于存储每一层的节点
    q.push(root); // 将根节点加入队列
    while (!q.empty()) { // 只要队列不为空,就继续执行
        TreeNode* node = q.front(); // 获取队列前端的节点
        q.pop(); // 移除已经访问的节点
        cout << node->value << " "; // 处理当前节点,这里是打印节点的值
        // 如果左子节点存在,加入队列
        if (node->left != nullptr) {
            q.push(node->left);
        }
        // 如果右子节点存在,加入队列
        if (node->right != nullptr) {
            q.push(node->right);
        }
    }
}

int main() {
    // 构建树
    TreeNode* root = new TreeNode(1);
    root->left = new TreeNode(2);
    root->right = new TreeNode(3);
    root->left->left = new TreeNode(4);
    root->left->right = new TreeNode(5);

    cout << "深度优先搜索结果: ";
    depthFirstSearch(root);
    cout << "广度优先搜索结果: ";
    breadthFirstSearch(root);

    // 清理分配的内存
    delete root->left->left;
    delete root->left->right;
    delete root->left;
    delete root->right;
    delete root;
    return 0;
}

#include <iostream>
#include <list>
#include <queue>
#include <vector>
using namespace std;

class Graph {
public:
    int V; // 图的顶点数
    list<int> *adj; // 邻接表
    Graph(int V); // 构造函数
    void addEdge(int v, int w); // 添加边
    void DFS(int v); // 深度优先搜索
    void BFS(int v); // 广度优先搜索
private:
    void DFSUtil(int v, vector<bool> &visited); // 用于DFS的辅助函数
};

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

void Graph::addEdge(int v, int w) {
    adj[v].push_back(w); // 添加v到w的边
}

void Graph::DFSUtil(int v, vector<bool> &visited) {
    visited[v] = true; // 标记当前节点为已访问
    cout << v << " ";
    // 递归访问所有未访问的邻居
    for (auto i = adj[v].begin(); i != adj[v].end(); ++i) {
        if (!visited[*i]) {
            DFSUtil(*i, visited);
        }
    }
}

void Graph::DFS(int v) {
    vector<bool> visited(V, false); // 初始化所有顶点为未访问
    DFSUtil(v, visited); // 从v开始DFS
}

void Graph::BFS(int v) {
    vector<bool> visited(V, false); // 初始化所有顶点为未访问
    queue<int> queue;
    visited[v] = true; // 标记起始节点为已访问
    queue.push(v); // 将起始节点加入队列
    while (!queue.empty()) {
        // 从队列中弹出一个顶点进行访问
        v = queue.front();
        cout << v << " ";
        queue.pop();
        // 获取所有未访问的邻居,标记为已访问,然后加入队列
        for (auto i = adj[v].begin(); i != adj[v].end(); ++i) {
            if (!visited[*i]) {
                visited[*i] = true;
                queue.push(*i);
            }
        }
    }
}

int main() {
    // 创建一个包含4个顶点的图
    Graph g(4);
    g.addEdge(0, 1);
    g.addEdge(0, 2);
    g.addEdge(1, 2);
    g.addEdge(2, 0);
    g.addEdge(2, 3);
    g.addEdge(3, 3);
    cout << "深度优先搜索(从顶点2开始):" << endl;
    g.DFS(2);
    cout << "\n广度优先搜索(从顶点2开始):" << endl;
    g.BFS(2);
    return 0;
}

十四、设置输出宽度以及小数点后几位

#include <iostream>
#include <iomanip> // 包含setw和setprecision
using namespace std;
int main() {
    double pi = 3.14159265;
    int number = 123;
    // 设置宽度为10,并填充空格
    cout << setw(10) << number << endl;
    // 设置宽度为10,填充空格,以及设置小数点后显示3位
    cout << setw(10) << setprecision(3) << pi << endl;
    // 设置宽度为10,填充空格,小数点后显示5位,并固定小数点表示法
    cout << setw(10) << setprecision(5) << fixed << pi << endl;
    // 如果想要后续的输出也保持这种格式设置,可以不重置宽度和精度
    // 重置精度为默认值,显示所有小数位
    cout << setprecision(0) << scientific; // 重置为科学计数法表示
    cout << pi << endl;
    return 0;
}

十五、哈希函数

#include <iostream>
#include <list>
using namespace std;
// 哈希表大小
#define HASH_TABLE_SIZE 10
class HashTable {
private:
    list<int> table[HASH_TABLE_SIZE];
    // 哈希函数
    int hashFunction(int x) {
        return x % HASH_TABLE_SIZE;
    }
public:
    // 插入
    void insertItem(int key) {
        int index = hashFunction(key);
        table[index].push_back(key);
    }
    // 删除
    void removeItem(int key) {
        int index = hashFunction(key);
        table[index].remove(key);
    }
    // 显示哈希表
    void displayHash() {
        for (int i = 0; i < HASH_TABLE_SIZE; i++) {
            cout << i;
            for (auto x : table[i])
              cout << " --> " << x;
            cout << endl;
        }
    }
};

int main() {
    HashTable ht;
    // 插入键到哈希表
    ht.insertItem(10);
    ht.insertItem(20);
    ht.insertItem(15);
    ht.insertItem(25);

    ht.removeItem(15);
    ht.displayHash();
    return 0;
}

十六、Dijkstra

Dijkstra算法是一种用于在图中找到从单一源点到所有其他节点的最短路径的算法

#include <iostream>
#include <vector>
#include <limits>
using namespace std;
// 定义无穷大为INT_MAX
const int INF = numeric_limits<int>::max();
// 找到最短路径树集合中距离最小的顶点
int minDistance(const vector<int>& dist, const vector<bool>& sptSet, int V) {
    int min = INF, min_index; 
    for (int v = 0; v < V; v++)
        if (!sptSet[v] && dist[v] <= min)
            min = dist[v], min_index = v;
    
    return min_index;
}

// 打印Dijkstra算法的结果
void printSolution(const vector<int>& dist, int V) {
    cout << "顶点 \t 距离源点的距离\n";
    for (int i = 0; i < V; i++)
        cout << i << " \t\t" << dist[i] << "\n";
}

// 实现Dijkstra算法
void dijkstra(const vector<vector<int>>& graph, int src, int V) {
    vector<int> dist(V, INF); // 距离数组,dist[i]保存从源到顶点i的最短距离
    vector<bool> sptSet(V, false); // sptSet[i]为true,如果顶点i已在最短路径树中,或距离为最短
    dist[src] = 0; // 源点到自身的距离总是0
    for (int count = 0; count < V - 1; count++) {
        int u = minDistance(dist, sptSet, V);   
        sptSet[u] = true;       
        for (int v = 0; v < V; v++)
            if (!sptSet[v] && graph[u][v] && dist[u] != INF && dist[u] + graph[u][v] < dist[v])
                dist[v] = dist[u] + graph[u][v];
    }
    printSolution(dist, V);
}

int main() {
    /* 创建图的示例 */
    int V = 9;
    vector<vector<int>> graph = {
        {0, 4, 0, 0, 0, 0, 0, 8, 0},
        {4, 0, 8, 0, 0, 0, 0, 11, 0},
        {0, 8, 0, 7, 0, 4, 0, 0, 2},
        {0, 0, 7, 0, 9, 14, 0, 0, 0},
        {0, 0, 0, 9, 0, 10, 0, 0, 0},
        {0, 0, 4, 14, 10, 0, 2, 0, 0},
        {0, 0, 0, 0, 0, 2, 0, 1, 6},
        {8, 11, 0, 0, 0, 0, 1, 0, 7},
        {0, 0, 2, 0, 0, 0, 6, 7, 0}
    };
    dijkstra(graph, 0, V); // 以顶点0为源点执行Dijkstra算法
    return 0;
}

十七、使用stringstream分割单词

string input;
getline(cin, input); // 获取整行输入
vector<string> words;
string word;
stringstream ss(input);
while (ss >> word) {
    words.push_back(word);
}
  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值