课程实训 @

简介 @

放一些学校数据结构课程实训的代码,一个为链表和文件操作实现的简易图书管理系统,另一个使用文件操作和最短路径算法实现计算最短路径。

简易图书管理系统 @

struct Book {                //图书结点
    string ISBN;
    string bookName;
    int price;
};
class BookCol {
private:
    Book *books;            //图书表基地址
    int MAXSIZEBOOKS;        //最大容量
    string FilePath;        //文件路径
    int num;                //当前数量
public:
    BookCol(string filePath) {
        //初始化
        FilePath = filePath;
        fstream file(FilePath);
        num = 0;
        books = NULL;
        file >> MAXSIZEBOOKS;                //读取当前容量

        //生成图书表
        books = new Book[MAXSIZEBOOKS];
        char temp[256];                        //字符缓存区
        int priceTemp = 0;                    //数字缓存区
        if (file.is_open()) {
            file.getline(temp, 100);
        }
        else{
            cout << "文件路径错误,回车键结束程序!" << endl;
            cin.get();
            exit(1);
        }
        file.getline(temp, 100);
        file >> temp;
        while (temp[0] != '\0') {
            setISBN(num, temp);
            file >> temp;
            setBookName(num, temp);
            file >> priceTemp;
            setPrice(num, priceTemp);
            file >> temp;
            num++;
        }
        file.close();
    }
    ~BookCol() {
        delete books;
    }
    //获取图书信息
    string getISBN(int i) {
        return books[i].ISBN;
    }
    string getBookName(int i) {
        return books[i].bookName;
    }
    int getPrice(int i) {
        return books[i].price;
    }

    //设置图书信息
    void setISBN(int i,string ISBN) {
        books[i].ISBN = ISBN;
    }
    void setBookName(int i,string bookName) {
        books[i].bookName = bookName;
    }
    void setPrice(int i, int price) {
        books[i].price = price;
    }

    void Increase() {                //扩容操作
        fstream file(FilePath);
        MAXSIZEBOOKS *= 2;
        file.clear();
        file << MAXSIZEBOOKS;

        //原数据移动到新空间
        Book *temp = new Book[MAXSIZEBOOKS];
        for (int i = 0; i < num; i++) {
            temp[i].bookName = getBookName(i);
            temp[i].ISBN = getISBN(i);
            temp[i].price = getPrice(i);
        }
        this->books = temp;
        file.close();
    }

    void delBook(string ISBN);        //图书删除
    int InsertBook();                //图书插入
    void revealBook(string ISBN);    //修改价格
    int findBook(string ISBN);        //图书查找
    void bookSort();                //图书排序
    int bookCount();                //图书数量
    void printBook();                //遍历图书信息
    void updataBook();                //文件更新
    void bookMenu();                //菜单显示
};
//显示菜单
void BookCol::bookMenu() {
    cout << "\t\t|--------0. 显示所有图书--------|" << endl;
    cout << "\t\t|--------1. 查找图书------------|" << endl;
    cout << "\t\t|--------2. 插入图书------------|" << endl;
    cout << "\t\t|--------3. 删除图书------------|" << endl;
    cout << "\t\t|--------4. 修改图书价格--------|" << endl;
    cout << "\t\t|--------5. 图书价格排序--------|" << endl;
    cout << "\t\t|--------6. 统计图书数量--------|" << endl;
    cout << "\t\t|--------q. 退出----------------|" << endl;
}
//更新数据
void BookCol::updataBook() {
    fstream file(FilePath, ios::out);
    file << MAXSIZEBOOKS << endl;
    file << "ISBN" << "            " << "图书名称" << "                " << "价格" << endl;
    for (int i = 0; i < num - 1; i++) {
        file << getISBN(i) << "\t\t" << getBookName(i) << "\t\t\t" << getPrice(i) << endl;
    }
    file.close();
}
//删除操作
void BookCol::delBook(string ISBN) {
    int i = findBook(ISBN);
    while (i < num-1) {
        setISBN(i, getISBN(i + 1));
        setBookName(i, getBookName(i + 1));
        setPrice(i, getPrice(i + 1));
        i++;
    }
    updataBook();    //更新文件
    num--;
}
//排序操作
void BookCol::bookSort() {
    Book temp;
    for (int i = 0; i < num; ++i) {
        temp = books[i];        //将待插入的数据存放入监视哨中
        int low = 0;
        int high = i - 1;
        while (low <= high) {
            int m = (low + high) / 2;
            if (temp.price < books[m].price) {
                high = m - 1;
            }
            else {
                low = m + 1;
            }
        }
        for (int j = i - 1; j >= high + 1; --j) {    //记录后移
            books[j + 1] = books[j];
        }
        books[high + 1] = temp;
    }
    updataBook();    //更新文件
    cout << "排序完成!" << endl;
}
//修改图书价格
void BookCol::revealBook(string ISBN) {
    int i = findBook(ISBN);
    cout << "输入修改的价格" << endl;
    int price;
    cin >> price;
    setPrice(i, price);
    updataBook();            //文件更新
    cout << "修改完成!" << endl;
}
//打印图书
void BookCol::printBook() {
    for (int i = 0; i < num; i++) {
        cout << "图书号:" << getISBN(i) <<" "<< "图书名称:" << getBookName(i) <<" "<< "图书价格:" << getPrice(i) <<endl;
    }
}
//插入图书
int BookCol::InsertBook(){
    string bookname; 
    int price; 
    string ISBN;
    if (num >= MAXSIZEBOOKS) {        //如果空间不足则扩容
        Increase();
    }
    cout << "请输入图书名称" << endl;
    cin >> bookname;
    setBookName(num, bookname);

    cout << "请输入图书价格" << endl;
    cin >> price;
    setPrice(num, price);

    cout << "请输入图书ISBN" << endl;
    cin >> ISBN;
    setISBN(num, ISBN);
    fstream file;
    file.open(FilePath, ios::app);
    file << ISBN << "        "<< bookname <<"            " << price << endl;
    file.close();
    num++;
    return 1;
}
//查找图书
int BookCol::findBook(string ISBN) {
    int i;
    int flog = 0;
    for (i = 0; i < MAXSIZEBOOKS; i++) {
        string isbn = getISBN(i);
        if (ISBN == isbn) { 
            flog = 1;
            break; 
        }
    }
    if(flog) return i;
    else return -1;
}
//统计图书
int BookCol::bookCount() {
    return num;
}
int main() {
    BookCol *b = new BookCol("F:\\program\\Test_project\\C-C++\\test'\\test'\\book.txt");
    int flag = 1;
    char ch;

    b->bookMenu();
    while (flag) {
        cin >> ch;
        switch (ch)
        {
        case '0': {
            b->printBook();
        }break;
        case '1': {
            string isbn;
            cout << "请输入ISBN号" << endl;
            cin >> isbn;
            int i = b->findBook(isbn);
            cout << "图书编号:" << b->getISBN(i) << " 图书名称:" << b->getBookName(i) << " 图书价格:" << b->getPrice(i) << endl;
        }break;
        case '2': {
            b->InsertBook();
        }break;
        case '3': {
            cout << "请输入ISBN号" << endl;
            string isbn;
            cin >> isbn;
            b->delBook(isbn);
        }break;
        case '4': {
            string isbn;
            cout << "请输入ISBN号" << endl;
            cin >> isbn;
            b->revealBook(isbn);
        }break;
        case '5': {
            b->bookSort();
        }break;
        case '6': {
            cout << "图书数量为:" << b->bookCount() << endl;
        }break;
        case 'q': {
            flag = 0;
        }break;
        default:
            break;
        }
    }
    cin.get();
    return 0;
}

图的最短路径 @

typedef struct VertexType {                //顶点信息
    char name[256];
    char intruction[256];
}VertexType;

typedef int EdgeType;                    //边上的权值
#define MAXVEX 100                        //最大顶点数
#define MAXINTS 65535                    //代表无穷大

typedef struct {
    VertexType vexs[MAXVEX];            //顶点表
    EdgeType arc[MAXVEX][MAXVEX];        //边矩阵
    int numVertexes, numEdges;            //图中当前节点数和边数
}MGraph;

/*
 *    返回顶点名称所在顶点表的位置
 */
int FindIndex(MGraph G, string name) {
    int i;
    for (i = 0; i < G.numVertexes; ++i) {
        if (G.vexs[i].name == name) {
            return i;
        }
    }
    return -1;
}
/*
 *    邻接矩阵的创建
 */
void CreateMgraph(MGraph *G,string ptr) {
    string start, end;        //起点,终点
    int w;                    //边上的权值

    //读取顶点数、边数
    fstream file(ptr);
    file >> G->numVertexes >> G->numEdges;

    //读取顶点信息
    for (int i = 0; i < G->numVertexes; i++) {
        file >> G->vexs[i].name;
        file >> G->vexs[i].intruction;
    }
    //初始化边权值
    for (int i = 0; i < G->numVertexes; i++) {
        for (int j = 0; j < G->numVertexes; j++) {
            G->arc[i][j] = MAXINTS;
        }
    }
    //读取边权值
    for (int k = 0; k < G->numEdges; k++) {
        file >> start >> end >> w;
        int i = FindIndex(*G, start);
        int j = FindIndex(*G, end);
        G->arc[i][j] = w;
        G->arc[j][i] = G->arc[i][j];        //矩阵对称
    }
    file.close();
}
/*
 *    更新文件信息
 */
void updataGrapg(MGraph G) {
    fstream file("F:\\program\\Test_project\\C-C++\\test'\\test'\\graph.txt");
    file << G.numVertexes << "\t" << G.numEdges << "\t" << endl;
    file << endl;
    for (int i = 0; i < G.numVertexes; i++) {
        file << G.vexs[i].name << "\t" << G.vexs[i].intruction << "\t" << endl;
    }
    file << endl;
    for (int i = 0; i < G.numVertexes; i++) {
        for (int j = i; j < G.numVertexes; j++) {
            if (G.arc[i][j] != MAXINTS) {
                file << G.vexs[i].name << "\t" << G.vexs[j].name << "\t" << G.arc[i][j] << endl;
            }
        }
    }
    file.close();
}
/* 
 *    若顶点存在,则修改此顶点的介绍信息,否则返回-1
 */
int ModifyInfo(MGraph *G,char name[],char newInfo[]) {
    int i = FindIndex(*G, name);
    if (i != -1) {
        G->vexs[i].intruction;
        strcpy_s(G->vexs[i].intruction, newInfo);
        updataGrapg(*G);
        return 1;
    }
    return -1;
}
/*
 *    若该顶点存在,则输出介绍信息,若顶点不存在则返回-1
 */
int Instruction(MGraph G,string name) {
    int i = FindIndex(G,name);
    if (i != -1) {
        cout << G.vexs[i].intruction << endl;
        return 1;
    }
    return -1;
}
/*
 * 顶点数小于最大顶点数,则添加成功
 */
int addVex(MGraph *G,char name[],char Info[]) {
    if (G->numVertexes < MAXVEX) {
        strcpy_s(G->vexs[G->numVertexes].name, name);
        strcpy_s(G->vexs[G->numVertexes].intruction, Info);
        for (int i = 0; i < G->numVertexes; i++) {
            G->arc[G->numVertexes][i] = MAXINTS;
            G->arc[i][G->numVertexes] = MAXINTS;
        }
        G->arc[G->numVertexes][G->numVertexes] = MAXINTS;
        G->numVertexes++;
        updataGrapg(*G);
        return 1;
    }
    return -1;
}
/*
 *    若该顶点存在,则删除该顶点,若该顶点不存在,则返回-1
 */
int delVex(MGraph *G, char name[]) {
    int i = FindIndex(*G,name);
    if (i != -1) {
        for (int j = i; j < G->numVertexes; ++j) {    //记录前移
            G->vexs[j] = G->vexs[j + 1];
        }
        G->numVertexes--;
        updataGrapg(*G);
        return 1;
    }
    return -1;
}
/*
 * 添加一条边,如果不存在此边,则添加成功,如果存在此边或者不存在相关顶点,添加失败返回-1
 */
int addArc(MGraph *G, char start[], char end[], EdgeType num) {
    int i = FindIndex(*G,start);
    int j = FindIndex(*G, end);
    if (i != -1 && j != -1) {
        if (G->arc[i][j] == MAXINTS){
            G->arc[i][j] = num;
            G->numEdges++;
            updataGrapg(*G);
        }
        else 
            return -1;
    }
    return 1;
}
/*
 *    若该边存在,则删除该边,该边不存在则返回-1
 */
int delArc(MGraph *G, char start[], char end[]) {
    int i = FindIndex(*G,start);
    int j = FindIndex(*G,end);
    if (i != -1 && j != -1) {
        if(G->arc[i][j] != MAXINTS)
        G->arc[i][j] = MAXINTS;            //将此边信息更新为无穷大
        G->numEdges--;
        updataGrapg(*G);
        return 1;
    }
    return -1;
}
/*
 *    打印所有边集信息,用于测试
 */
void PrintMg(MGraph G) {
    for (int i = 0; i < G.numVertexes; i++) {
        for (int j = 0; j < G.numVertexes; j++) {
            cout << G.vexs[i].name << "--" << G.vexs[j].name << "--" << G.arc[i][j] << " |";
        }
        cout << endl;
    }
}
/*
 *    打印所有顶点信息
 */
void PrintVex(MGraph G) {
    cout << "该学校的景点有:" << endl;
    for (int i = 0; i < G.numVertexes; ++i) {
        cout << "\t" << i + 1 << ". " << G.vexs[i].name << endl;
    }
    cout << "----------------------------------" << endl;
}
/*
 *    最短路径,迪杰斯特拉算法,若未找到顶点则返回-1
 */
int ShortesPath_DIJ(MGraph G, char start[], char end[]) {
    int n = G.numVertexes;
    int *S = (int*)malloc(sizeof(int) * n);
    int *D = (int*)malloc(sizeof(int) * n);
    int *Path = (int*)malloc(sizeof(int) * n);

    int v0 = FindIndex(G, start);
    int vt = FindIndex(G, end);
    if (v0 == -1 || vt == -1) {
        cout << "顶点未找到 " << end;
        return -1;
    }
    for (int v = 0; v < n; ++v) {            //初始化
        S[v] = false;
        D[v] = G.arc[v0][v];                //记录v0到v的最短路径长度
        if (D[v] < MAXINTS) {                //如果有弧,更新Path为v0,否则置为-1
            Path[v] = v0;
        }
        else {
            Path[v] = -1;
        }
    }
    S[v0] = true;       //将v0加入S
    D[v0] = 0;            //源点到源点的距离为0

    //遍历其余顶点,每次求得v0到某个顶点v的最短路径,将v并入S
    for (int i = 1; i < n; ++i) {
        int min = MAXINTS;
        int v;
        for (int w = 0; w < n; ++w) {
            if (!S[w] && D[w] < min) {
                v = w;                    //保存顶点位置
                min = D[w];
            }
        }
        S[v] = true;
        for (int w = 0; w < n; ++w) {
            if (!S[w] && (D[v] + G.arc[v][w] < D[w])) {
                D[w] = D[v] + G.arc[v][w];
                Path[w] = v;
            }
        }
    }    return D[vt];
}
void menu() {
    cout << "\t\t\t|---------------------------------|" << endl;
    cout << "\t\t\t|---1. 查询景点信息---------------|" << endl;
    cout << "\t\t\t|---2. 问路查询-------------------|" << endl;
    cout << "\t\t\t|---3. 增加一个景点及其相关信息---|" << endl;
    cout << "\t\t\t|---4. 修改一个景点的相关信息-----|" << endl;
    cout << "\t\t\t|---5. 增加一条新的路径-----------|" << endl;
    cout << "\t\t\t|---6. 删除一条路径---------------|" << endl;
    cout << "\t\t\t|---7. 删除一个景点---------------|" << endl;
    cout << "\t\t\t|---0. 退出系统-------------------|" << endl;
    cout << "\t\t\t|---------------------------------|" << endl;
    cout << endl;
}
int main() {
    MGraph G;
    string ptr = "F:\\program\\Test_project\\C-C++\\test'\\test'\\graph.txt";
    CreateMgraph(&G,ptr);
    int flag = 1;
    char c;
    menu();
    PrintVex(G);
    while (flag) {
        cout << "请选择功能" << endl;
        cout << "----------------------------------" << endl;
        cin >> c;
        switch (c)
        {
        case '1': {
            char name[256];
            cout << "请输入景点名称" << endl;
            cin >> name;
            Instruction(G, name);
        }break;
        case '2': {
            char start[256];
            char end[256];
            cout << "请输入起点名称" << endl;
            cin >> start;
            cout << "请输入终点名称" << endl;
            cin >> end;
            int l = ShortesPath_DIJ(G, start, end);
            if(l != MAXINTS){
                cout << "路径长度为:" << l << endl;
            }
            else {
                cout << "不存在此路径" << endl;
            }
        }break;
        case '3': {
            char name[256];
            char Info[256];
            cout << "请输入景点名称" << endl;
            cin >> name;
            cout << "请输入景点介绍" << endl;
            cin >> Info;
            if(addVex(&G, name, Info)){
                cout << "添加景点成功" << endl;
            }
            else {
                cout << "添加景点失败" << endl;
            }
        }break;
        case '4': {
            char name[256];
            char Info[256];
            cout << "请输入景点名称" << endl;
            cin >> name;
            cout << "请输入此景点新的介绍" << endl;
            cin >> Info;
            if(ModifyInfo(&G, name, Info)){
                cout << "修改成功" << endl;
            }
            else {
                cout << "修改失败" << endl;
            }
        }break;
        case '5': {
            char start[256];
            char end[256];
            int length;
            cout << "请输入路径起点" << endl;
            cin >> start;
            cout << "请输入路径终点" << endl;
            cin >> end;
            cout << "请输入路径距离" << endl;
            cin >> length;
            if (addArc(&G, start, end, length)) {
                cout << "添加路径成功" << endl;
            }
            else {
                cout << "添加路径失败" << endl;
            }
        }break;
        case '6': {
            char start[256];
            char end [256];
            cout << "请输入起点位置" << endl;
            cin >> start;
            cout << "请输入终点位置" << endl;
            cin >> end;
            if (delArc(&G, start, end) != -1) {
                cout << "路径删除成功" << endl;
            }
            else{
                cout << "路径删除失败" << endl;
            }
        }break;
        case '7': {
            char name[256];
            cout << "请输入景点名称" << endl;
            cin >> name;
            if (delVex(&G, name)) {
                cout << "删除景点成功" << endl;
            }
            else{
                cout << "删除景点失败" << endl;
            }
        }break;
        case '0': {
            exit(1);
        }break;
        default:
            cout << "操作有误" << endl;
            break;
        }
    }return 0;
}