稀疏数组 C++练习

 

韩顺平老师数据结构与算法 P7-P9

 007_尚硅谷_稀疏数组的应用场景_哔哩哔哩_bilibili

 

 

 

 

 

 

 

 

 

 

/* 尚硅谷-韩顺平-数据结构与算法.cpp : Defines the entry point for the console application.
BV1E4411H73v
*/
using namespace std;
#include <iostream>
#include <vector>
#include <map>
#include <fstream>


//SparsItem为步骤相应的行,列,值数据
class SparsItem{
public:
    int s_row;
    int s_col;
    int s_val;
    SparsItem(){

    }
    SparsItem(int row, int col, int val){
        this->s_row = row;
        this->s_col = col;
        this->s_val = val;
    }
};


//map<pair(int, SparsItem)> m_sitem;
class MyArray{
public:
    //建立一个MAP用于存放具体的稀疏数组的行数据,int为步骤数,SparsItem为步骤相应的行,列,值数据
    //map中存放的数据格式为 map<make_pair(步骤数int, SparsItem{行数int, 列数int, 值int})>
    map<int, SparsItem> m_sitem;
    int maxrow = 11;
    int maxcol = 11;
    //用于记录稀疏数组有多少个值,也就是五子棋中走了多少步
    int steps = 0;
    


    //获取数组的首地址,行数和列数,传入的行数和列数进行遍历,实现通用性
    void convertToSpars(int *a, int maxrow = 11, int maxcol = 11, int defaultval = 0){
        //清空稀疏数组内容
        this->m_sitem.clear();
        //外部传入这个二维数组的行列,默认为11
        this->maxrow = maxrow;
        this->maxcol = maxcol;
        this->steps = 0;

        //依次遍历数组中所有的元素,当元素不与默认值相同,则进行m_sitem内容的添加
        for (int i = 0; i < this->maxrow; i++){
            for (int j = 0; j < this->maxcol; j++){
                if (a[i * this->maxcol + j] != defaultval){
                    m_sitem.insert(make_pair(++(this->steps), SparsItem(i, j, a[i * this->maxcol + j])));
                }
            }
        }

        //测试打印map中的内容
        cout << "测试打印map中的内容" << endl;
        for (map<int, SparsItem>::iterator it = this->m_sitem.begin(); it != this->m_sitem.end();it++){
            cout << "步骤号是: " << (*it).first << " 行,列,值: " << (*it).second.s_row << " " << (*it).second.s_col << " " << (*it).second.s_val << endl;
        }

        this->saveSparsToFile();
    }

    void saveSparsToFile(){
        //创建文件对象,如果打开失败则直接返回
        ofstream ofs;
        ofs.open("spartfile.txt", ios::out);
        if (!ofs.is_open()){
            cout << "spartfile.txt打开失败" << endl;
            return;
        }

        //首先写入首行内容,编号固定为0, 内容为总行数,总列数,有效数据数量
        ofs << 0 << " ";
        ofs << this->maxrow << " ";
        ofs << this->maxcol << " ";
        ofs << this->steps << endl;

        //通过for循环依次写入每一步的内容
        for (int i = 1; i < this->steps + 1; i++){
            ofs << i  << " ";
            ofs << this->m_sitem[i].s_row << " ";
            ofs << this->m_sitem[i].s_col << " ";
            ofs << this->m_sitem[i].s_val << endl;
        }
        //关闭文件对象
        ofs.close();
    }

    //从文件中读取稀疏数组并转换为普通二维数组,可以指定默认值,不指定则普通数组默认值为0
    void readFromFile(int defaltval = 0){

        //以读取方式打开文件spartfile.txt
        ifstream ifs;
        ifs.open("spartfile.txt", ios::in);
        if (!ifs.is_open()){
            cout << "spartfile.txt打开失败" << endl;
            return;
        }

        //二维数组由二维vector来实现,比较容易
        vector <vector<int>> v;
        //读取第一行内容,第一行为稀疏数组的元数据
        int totalsteps;
        ifs >> this->steps;
        ifs >> this->maxrow;
        ifs >> this->maxcol;
        ifs >> totalsteps;
        //cout << "this->maxrow " << this->maxrow << " this->maxcol " << this->maxcol << endl;
        //cout << "ifs >> this->steps " << this->steps << endl;
        //for循环总行数,每次循环创建一个vector容器,尺寸为maxcol个元素,初始值为传入的参数,默认值为0
        for (int i = 0; i < this->maxrow; i++){
            v.push_back(vector<int>(this->maxcol, defaltval));
        }
        //测试打印刚创建的二维vector
        cout << "测试打印刚创建的二维vector" << endl;
        for (int i = 0; i < this->maxrow; i++){
            for (int j = 0; j < this->maxcol; j++){
                cout << v[i][j] << "\t";
            }
            cout << endl;
        }
        cout << "--------------------------" << endl;

        //清空map容器
        this->m_sitem.clear();
        int step;
        int row;
        int col;
        int val;
        //循环读取文件中的内容,由于之前已经读取过一行元数据,实际这个循环是从第二行开始读取的
        //每次循环做两件事情,第一个是向内部的map添加内容,第二是修改二维vector的相应内容
        while (ifs >> step && ifs >> row && ifs >> col && ifs >> val){
            this->m_sitem.insert(make_pair(step, SparsItem(row, col, val)));
            v[row][col] = val;
        }

        //关闭文件对象
        ifs.close();

        //打印从稀疏数组恢复的二维数组
        cout << "打印从稀疏数组恢复的二维数组" << endl;
        for (int i = 0; i < this->maxrow; i++){
            for (int j = 0; j < this->maxcol; j++){
                cout << v[i][j] << "\t";
            }
            cout << endl;
        }
        cout << "--------------------------" << endl;

        //测试打印map中的内容
        cout << "测试打印map中的内容" << endl;
        for (map<int, SparsItem>::iterator it = this->m_sitem.begin(); it != this->m_sitem.end(); it++){
            cout << "步骤号是: " << (*it).first << " 行,列,值: " << (*it).second.s_row << " " << (*it).second.s_col << " " << (*it).second.s_val << endl;
        }

    }
};

void main(){
    int dArray[11][11] = {
        { 0, 0, 0, 22, 0, 0, 15 },
        { 0, 11, 0, 0, 0, 17, 0 },
        { 0, 0, 0, -6, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 39, 0 },
        { 91, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 28, 0, 0, 0, 0 },
    };




    //cout << "sizeof(dArray[0]) / sizeof(dArray[0][0]) = " << sizeof(dArray[0]) / sizeof(dArray[0][0]) << endl;
    //cout << "sizeof(dArray) / sizeof(dArray[0]) = " << sizeof(dArray) / sizeof(dArray[0]) << endl;

    MyArray m;
    /*        以一维数组的形式传进去
    // sizeof(dArray) / sizeof(dArray[0])代表行数,数组总大小/数组每行的大小
     sizeof(dArray[0]) / sizeof(dArray[0][0])代表列数,数组行大小/数组每个元素大小
     */
    //m.convertToSpars((int*)dArray, sizeof(dArray) / sizeof(dArray[0]), sizeof(dArray[0]) / sizeof(dArray[0][0]));

    int choice;
    while (true)
    {
        //测试打印原始二维数组
        cout << "测试打印原始二维数组" << endl;
        for (int i = 0; i < 11; i++){
            for (int j = 0; j < 11; j++){
                cout << dArray[i][j] << "\t";
            }
            cout << endl;
        }
        cout << "-------------------------------" << endl;

        cout << "测试功能" << endl;
        cout << "1. 测试从普通二维数组转为稀疏数组并保存文件" << endl;
        cout << "2. 测试从文件读出稀疏数组并还原成二维数组" << endl;
        cout << "3. 退出" << endl;
        cin >> choice;
        if (cin.fail()){
            cin.clear();
            cin.sync();
        }
        switch (choice)
        {
        case 1:
            m.convertToSpars((int*)dArray, sizeof(dArray) / sizeof(dArray[0]), sizeof(dArray[0]) / sizeof(dArray[0][0]));;
            system("pause");
            break;
        case 2:
            m.readFromFile();
            system("pause");
            break;
        case 3:
            return;
        default:
            break;
        }
        system("cls");
    }

}

 

posted @ 2022-07-26 23:20  Greatday  阅读(41)  评论(0)    收藏  举报