You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++中实现带连接线的层级式排行榜可视化?

如何在C++中实现带连接线的层级式排行榜?

我尝试用vector实现层级排行榜,但排版不够规整,想添加如下样式的连接线,直到第31名:

Rank1
                                      |
               +----------------------+-----------------------+
            Rank2                                            Rank3
              |                                               |
   +----------+----------+                           +--------+--------+
Rank4                   Rank5                      Rank6              Rank7

以下是我目前的代码:

#include <iostream>
#include <vector>
#include <string>

using namespace std;

// 打印一行获奖者
void printRow(const vector<string>& row, int totalWidth) {
    int elements = row.size();
    int spaceBetween = (totalWidth - elements) / (elements + 1);
    for (int i = 0; i < elements; ++i) {
        for (int j = 0; j < spaceBetween; ++j)
            cout << " ";
        cout << row[i];
    }
    cout << endl;
}

// 打印获奖者图表
void printWinnersChart() {
    vector<vector<string>> winnersChart = {
        {"Bob"},
        {"Alice", "Charlie"},
        {"David", "Eve", "Frank", "Grace"},
        {"Henry", "Isabella", "Jack", "Kate", "Liam", "Mia", "Noah", "Olivia"},
        {"Penelope", "Quinn", "Ryan", "Sophia", "Thomas", "Uma", "Victoria", "William", "Xavier", "Yara", "Zoe", "Adam", "Bella", "Caleb", "Diana", "Ethan"}
    };

    int totalWidth = 80;

    for (const auto& row : winnersChart) {
        printRow(row, totalWidth);
    }
}

int main() {
    cout << "Figure 2: Sample of the winners' chart" << endl;
    printWinnersChart();

    // 等待用户按回车退出终端
    cin.get();

    return 0;
}

解决方案

要实现带连接线的层级式排行榜,核心是计算每一层每个元素的位置,再根据父子元素的位置关系绘制连接线。以下是修改后的完整代码:

#include <iostream>
#include <vector>
#include <string>

using namespace std;

// 存储元素的位置信息
struct ElementPos {
    string name;
    int start; // 元素起始坐标
    int mid;   // 元素中间坐标
};

// 打印一行元素并记录每个元素的位置
void printRowAndRecordPos(const vector<string>& row, int totalWidth, vector<ElementPos>& posList) {
    posList.clear();
    int elementCount = row.size();
    
    // 计算所有元素的总长度
    int totalNameLen = 0;
    for (const string& name : row) {
        totalNameLen += name.size();
    }
    // 计算元素间的间隔
    int spaceBetween = (totalWidth - totalNameLen) / (elementCount + 1);

    int currentPos = spaceBetween;
    for (const string& name : row) {
        // 打印前置空格
        cout << string(currentPos, ' ');
        cout << name;
        // 记录位置
        ElementPos pos;
        pos.name = name;
        pos.start = currentPos;
        pos.mid = currentPos + name.size() / 2;
        posList.push_back(pos);
        // 更新下一个元素的起始位置
        currentPos += name.size() + spaceBetween;
    }
    cout << endl;
}

// 打印当前行与下一行之间的连接线
void printConnectors(const vector<ElementPos>& upperPos, const vector<ElementPos>& lowerPos, int totalWidth) {
    // 第一行:上层元素的竖线
    string line(totalWidth, ' ');
    for (const ElementPos& pos : upperPos) {
        line[pos.mid] = '|';
    }
    cout << line << endl;

    // 第二行:横线与分叉点
    line.assign(totalWidth, ' ');
    for (int i = 0; i < upperPos.size(); ++i) {
        int upperMid = upperPos[i].mid;
        // 找到当前上层元素对应的两个下层元素
        int leftIdx = 2 * i;
        int rightIdx = 2 * i + 1;
        if (leftIdx >= lowerPos.size() || rightIdx >= lowerPos.size()) {
            continue;
        }
        int leftMid = lowerPos[leftIdx].mid;
        int rightMid = lowerPos[rightIdx].mid;

        // 绘制中间连接点
        line[upperMid] = '+';
        // 绘制左侧横线
        for (int j = leftMid; j < upperMid; ++j) {
            line[j] = '-';
        }
        // 绘制右侧横线
        for (int j = upperMid + 1; j <= rightMid; ++j) {
            line[j] = '-';
        }
        // 绘制左右连接点
        line[leftMid] = '+';
        line[rightMid] = '+';
    }
    cout << line << endl;
}

// 打印完整层级排行榜
void printWinnersChart() {
    vector<vector<string>> winnersChart = {
        {"Bob"},
        {"Alice", "Charlie"},
        {"David", "Eve", "Frank", "Grace"},
        {"Henry", "Isabella", "Jack", "Kate", "Liam", "Mia", "Noah", "Olivia"},
        {"Penelope", "Quinn", "Ryan", "Sophia", "Thomas", "Uma", "Victoria", "William", "Xavier", "Yara", "Zoe", "Adam", "Bella", "Caleb", "Diana", "Ethan"}
    };

    int totalWidth = 120; // 加宽总宽度适配多层级排版
    vector<ElementPos> prevPos;

    for (size_t i = 0; i < winnersChart.size(); ++i) {
        vector<ElementPos> currentPos;
        printRowAndRecordPos(winnersChart[i], totalWidth, currentPos);

        // 非最后一行则打印连接线
        if (i < winnersChart.size() - 1) {
            printConnectors(currentPos, prevPos, totalWidth);
        }
        prevPos = currentPos;
    }
}

int main() {
    cout << "Figure 2: 获奖者排行榜示例" << endl;
    printWinnersChart();

    // 等待用户按回车退出
    cin.get();

    return 0;
}

关键说明

  1. 位置记录:通过ElementPos结构体记录每个元素的起始和中间坐标,这是精准绘制连接线的核心依据。
  2. 连接线逻辑:先绘制上层元素的竖线,再通过横线连接上层元素与对应的两个下层元素,用+标记分叉点。
  3. 宽度适配:将总宽度设为120,避免层级增多后排版拥挤,可根据实际元素长度调整该值。
  4. 层级对应:默认每一层元素数量是上一层的2倍(符合示例中的层级规律),若你的层级结构不同,需调整leftIdx和rightIdx的计算逻辑。

内容的提问来源于stack exchange,提问作者SaveSecure

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 20:07:01