文本文件单词统计 & 构造可以使n个城市连接的最小生成树 & 交通咨询系统(最短路径问题

数据结构课程设计, 随便写的, 见笑了
二三题写在一块了,自己拆分一下

题目一 文本文件单词统计
1.1【问题描述】
编写一个文本文件单词统计的程序,包括建立文件、单词统计、单词查询、单词定位的功能。
1.2 【基本要求】
程序应先询问用户的ID号(ID号包括两个大写字母和4 位数字),例如:
请输入用户 ID 号 :AB1234
程序应对输入的 ID 号验证,符合 ID 号要求的格式,然后程序提示四种选择:
(1) 建立文件
(2) 单词统计
(3) 单词查询及定位
(4) 退出
注意:
i) 文件至少包含50个英文单词(一定出现重复的单词,且一定包含数字)
ii) 文档不规范,单词之间可能不只有一个空格,并且有加引号的一些单词“jiaozi”
加引号的单词算单词,但数字不算单词
iii) 逐行扫描文本文件,计算文档中单词总数,及各个单词出现的频次,并且按照单词首字母abcd……
的顺序排列,显示并生成soft.txt文件
iv) 查询任意给出的单词是否存在,如果不存在,在屏幕上输出“ 查无此词! ”;如果存在,显示单词
出现的总次数,并且详细列出其出现的位置。
例如: 请您输入待查询的词: of
单词 of 共出现了 2 次;
第 1 次出现在第 1 行,第 5 个位置;
第 2 次出现在第 3 行,第 1 个位置。
请您输入待查询的词:
1.3 【源代码】

package DataStructureDesign.Demo;

import java.io.*;
import java.util.ArrayList;
import java.util.Map;
import java.util.Scanner;
import java.util.TreeMap;
import java.util.regex.Pattern;

@SuppressWarnings("all")
public class Processor {
    private String path; // 文件路径
    private Map<String, ArrayList> hashTab; // 逻辑输出 单词:出现位置组成的链表始址
    private static final Pattern NUMBER_PATTERN = Pattern.compile("-?\\d+(\\.\\d+)?");

    public Map<String, ArrayList> getHashTab() {
        return hashTab;
    }

    public Processor() {
        this.path = null;
        this.hashTab = new TreeMap<>();
    }

    public void touchFile(User user) throws IOException {
        String dirName = "D:\\files\\" + user.getId();
        new File(dirName).mkdirs();

        System.out.print("请输入文件名:");
        Scanner sc = new Scanner(System.in);
        path = dirName + "\\" + sc.next();
        sc.nextLine();

        File file = new File(path);
        if (file.exists()) {
            System.out.println("文件已存在!");
            return;
        }

        file.createNewFile();
        FileWriter writer = new FileWriter(file.getAbsolutePath());
        // 向文件写入内容
        System.out.println("请输入文本:(按'q'退出输入)");
        String str = "";
        while (sc.hasNextLine()) {
            str = sc.nextLine();
            if (str.equals("q"))
                break;
            writer.write(str + '\n');
        }
        writer.flush();
        writer.close();
    }

    public String whichFile(User user) {
        System.out.println("是否选择当前文件?" + path);
        byte useCurrent = new Scanner(System.in).nextByte();
        if (useCurrent == 0 || path == null) {
            this.hashTab.clear();
            System.out.print("请输入想要 统计词频/单词查询 的文件名");
            path = "D:\\files\\" + user.getId() + "\\" + new Scanner(System.in).next();
        }
        return path;
    }

    public static String stringFormatting(String str) {
        str = str.replaceAll("\"", "");
        str = str.replaceAll("\\p{Punct}", "");
        str = str.replaceAll("\\s+"," ");
        str = str.toLowerCase();

        return str;
    }

    public static boolean neededToBeCounted(String str) {
        boolean isNumeric = str != null && NUMBER_PATTERN.matcher(str).matches();
        return !isNumeric;
    }

    /**
     * @throws FileNotFoundException
     * @description : 逐行读取文件, 得到一张以单词为键,其各出现位置所组成的链表始址为值的哈希表
     * @param : void
     * @return : void
     */
    public void wordFrequency() throws FileNotFoundException {
        try {
            hashTab.clear();
            File file = new File(path);
            BufferedReader in = new BufferedReader(new FileReader(file.getAbsolutePath()));
            String str;
            String[] strArr;
            int row = 0;

            while ((str = in.readLine()) != null) {
                str = stringFormatting(str);
                strArr = str.split(" ");

                for (int col = 0; col < strArr.length; col++) {
                    if (neededToBeCounted(strArr[col])) {
                        if (!hashTab.containsKey(strArr[col])) {
                            ArrayList<Integer[]> list = new ArrayList<>();
                            hashTab.put(strArr[col], list);
                            list.add(new Integer[]{row + 1, col + 1});
                        } else
                            hashTab.get(strArr[col]).add(new Integer[]{row + 1, col + 1});
                    }
                } // for
                row++;
            } // while
        } // try
        catch (IOException e) {
            path = null;
            System.out.println("文件不存在!");
        }
    }

    public void printResult() {

        int cnt = 0;
        for (String str: hashTab.keySet()
        ) {
            int tmp = hashTab.get(str).size();
            cnt += tmp;
            System.out.println("单词:" + str + ' ' + ' ' + "出现次数:" + tmp);
        }
        System.out.println("单词总数:" + cnt);
    }

    public void query(String word) {
        if (hashTab.containsKey(word)) {
            ArrayList<Integer[]> list = hashTab.get(word);
            int frequency = list.size(); //各出现位置所组成的链表的长度即为该单词出现的次数
            System.out.println("单词" + word + "共出现了" + frequency + "次");

            int i = 1;
            for (Integer[] tmp: list
            ) {
                System.out.println("第" + i++ + "次" + "出现在第" + tmp[0] + "行" + ",第" + tmp[1] + "个位置。");
            }
        } // if (hashTab.containsKey(word))
        else {
            System.out.println("查无此词!");
        }
    }
}
package DataStructureDesign.Demo;

import java.io.IOException;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) throws IOException {

        Scanner sc = new Scanner(System.in);
        User user = new User();
        System.out.print("请输入用户ID号:");
        while (!user.setId(sc.next()))
            System.out.println("id号不合法,请重新输入");

        int option;

        Processor pc = new Processor();

        while (true) {
            System.out.println("(1)建立文件");
            System.out.println("(2)单词统计");
            System.out.println("(3)单词查询及定位");
            System.out.println("(4)退出");
            do {
                option = new Scanner(System.in).nextInt();
            } while (option < 1 || option > 4);
            if (4 == option)
                break;

            switch (option) {
                case 1:
                    pc.touchFile(user);
                    break;

                case 2:
                    pc.whichFile(user);
                    pc.wordFrequency();
                    pc.printResult();
                    break;

                case 3:
                    pc.whichFile(user);

                    if (pc.getHashTab().isEmpty())
                        pc.wordFrequency();

                    String str;
                    while (sc.hasNextLine()) {
                        System.out.print("请您输入待查询的词:(按'q'退出)");
                        str = sc.next();
                        if (str.equals("q"))
                            break;
                        pc.query(str);
                    }
                    break;
            } // switch
        } // while (true)
    } // psvm
}
package DataStructureDesign.Demo;

public class User {

    private String id;
    private static final int DIGIT = 6;

    public String getId() {
        return id;
    }

    public boolean setId(String id) {
        boolean result = isAuthorized(id);
        if (result)
            this.id = id;
        return result;
    }

    public boolean isAuthorized(String id) {
        char[] tmp = id.toCharArray();

        if (tmp.length != 6)
            return false;

        for (int i = 0; i < DIGIT; i++) {
            if (i < 2) {
                if (tmp[i] < 65 || tmp[i] > 90)
                    return false;
            }
            else {
                if (tmp[i] < 48 || tmp[i] > 57)
                    return false;
            }
        } // for
        return true;
    }
}

题目二 构造可以使n个城市连接的最小生成树

2.1【问题描述】
给定一个地区的n个城市间的距离网,用Prim算法和Kruskal算法建立最小生成树,并计算得到的最小生成树的代价。
2.2【设计及分析】
程序包含6个模块:
(1) 输入城市信息;城市之间的距离网用邻接矩阵表示,如图1所示。(至少要求5个城市,9条边,设定9999为不可达)
(2 )打印城市信息和城市之间的直接可达距离;
输出格式要求: 城市的列表如下,共有 5 个城市:
( 1 )太原 ( 2 )北京 ( 3 )上海
( 4 )深圳 ( 5 )广州
太原到北京距离 15 万公里;
太原到上海距离 20 万公里;
太原到广州不能直接到达;
注意: 城市及编号可以任意设定,但必须按输出格式要求显示;距离和可否直接可达可以虚构。
(3 )判断是否为连通图;(可利用图的遍历来解决连通性问题)
(4 )用Prim 算法求最小生成树,并显示最小生成树的代价
(5 )用Kruskal 算法求最小生成树,并显示最小生成树的代价
(6 )退出
报告包含:
(1)简述图遍历算法,并画出算法实现的流程图;
(2)简述Prim算法和Kruskal算法,并画出Prim算法和Kruskal算法实现的流程图。分析两个算法的异同。

题目三 交通咨询系统(最短路径问题)
3.1【问题描述】
给定一个地区的n个城市间的距离网,计算任意两个城市之间的最短路径。
3.2 【基本要求】
程序包含4个模块:
(1 )输入城市信息;城市之间的距离网用邻接矩阵表示,如图2所示。(至少要求6个城市,10条边,设定9999为不可达)
(2 )打印城市信息和城市之间的直接可达距离;
输出格式要求: 城市的列表如下,共有 5 个城市:
( 1 )太原 ( 2 )北京 ( 3 )上海
( 4 )深圳 ( 5 )广州
太原到北京距离 15 万公里;
太原到上海距离 20 万公里;
太原到广州不能直接到达;
注意: 城市及编号可以任意设定,但必须按输出格式要求显示;距离和可否直接可达可以虚构。
(3 )计算任意两个城市之间的最短路径;
格式要求:提示用户输入选择的起点城市序号和终点城市序号,如果输入的城市序号不在,提示出错并请用户重新输入;
输出起点城市到终点城市的最短路径及路径长度
(4 )退出
报告包含:
简述算法过程,并画出算法实现的流程图

3.3【源代码】

#include<stdio.h>
#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

typedef char VertexType;
typedef int EdgeType;

#define MAXVEX 100
#define INFINITY 65535

typedef struct {
    VertexType vexs[MAXVEX]; // 顶点数组
    EdgeType arc[MAXVEX][MAXVEX]; // 邻接矩阵
    int numVertexes, numEdges; // 顶点数和边数
    int numConnectedComponent; // 连通分量数
} MGraph;

char visited[MAXVEX];

char cityList[10][10] = {"太原", "北京", "上海", "深圳", "广州"};

void createMGraph(MGraph *G) {
    int i, j, k, w;
    G->numConnectedComponent = 0;
    // printf("输入顶点数和边数:\n");
    scanf("%d %d", &G->numVertexes, &G->numEdges);
    // for (i = 0; i < G->numVertexes; i++) {
    //     scanf(&G->vexs[i]);
    // }

    for (i = 0; i < G->numVertexes; i++)
        for (j = 0; j < G->numVertexes; j++)
            G->arc[i][j] = INFINITY;

    for (k = 0; k < G->numEdges; k++) {
        // printf("输入边(vi, vj)上的下标i, 下标j和权w:\n");
        scanf("%d %d %d", &i, &j, &w);
        G->arc[i][j] = w;
        G->arc[j][i] = G->arc[i][j];
    }
}

bool isLegal(EdgeType e) {
    return e>0 && e<INFINITY;
}

void DFS(MGraph &G, int i) {

    visited[i] = 1;
    // printf("城市名:%s\n", cityList[i]);

    for (int j = 0; j < G.numVertexes; j++) {
        if (isLegal(G.arc[i][j]) && !visited[j])
            DFS(G, j);

    }
}

void DFSTraverse(MGraph &G) {

    int i;
    for (i = 0; i < G.numVertexes; i++)
        visited[i] = 0;
    for (i = 0; i < G.numVertexes; i++)
        if (!visited[i]) {
            DFS(G, i);
            G.numConnectedComponent++;
        }
}

void printInfo(MGraph &G) {
    printf("城市的列表如下, 共有%d个城市:\n", G.numVertexes);
    for (int i = 0; i < G.numVertexes; i++) {
        printf("(%d) %s ", i+1, cityList[i]);
        if (i%2==0 && i!=0)
            printf("\n"); // 逢3换行显示
    }

    for (int i = 0; i < G.numVertexes; i++) {
        for (int j = 0; j < G.numVertexes; j++) {
            if (i == j)
                continue;
            else if (G.arc[i][j] == INFINITY)
                printf("%s到%s不能直接到达\n", cityList[i], cityList[j]);
            else
                printf("%s到%s距离%d公里\n", cityList[i], cityList[j], G.arc[i][j]);
        }
        printf("===================================\n");
    }

    DFSTraverse(G);
    if (G.numConnectedComponent == 1)
        printf("该交通网是连通的\n");
    else
        printf("该交通网是不连通的\n");
}

void miniSpanTree_Prim(MGraph G) {
    int min, i, j, k;
    int adjVex[MAXVEX];
    int lowCost[MAXVEX];
    lowCost[0] = 0;
    adjVex[0] = 0;

    for (i = 1; i < G.numVertexes; i++) {
        lowCost[i] = G.arc[0][i];
        adjVex[i] = 0;
    }

    for (i = 1; i < G.numVertexes; i++) {
        min = INFINITY;
        j = 1; k = 0;
        while (j < G.numVertexes) {
            if (lowCost[j]!=0 && lowCost[j]<min) {
                min = lowCost[j];
                k = j;
            }
            j++;
        }

        printf("(%d, %d)", adjVex[k], k);
        lowCost[k] = 0;
        for (j = 1; j < G.numVertexes; j++) {
            if (lowCost[j]!=0 && G.arc[k][j]<lowCost[j]) {
                lowCost[j] = G.arc[k][j];
                adjVex[j] = k;
            }
        }
    }
}

#define MAXEDGE 15

typedef struct {
    int begin;
    int end;
    int weight;
} Edge;


int find(int *parents, int f) {
    while (parents[f] > 0)
        f = parents[f];
    return f;
}

bool compare(const Edge &e1, const Edge &e2) {	
	 return e1.weight <= e2.weight;  //权重从小到大排序
}


void miniSpanTree_Kruscal(MGraph G) {
    int i, n, m;
    int parents[MAXVEX];

    vector<Edge> edges;
    for (i = 0; i < G.numVertexes; i++)
        parents[i] = 0;

    for (int j = 0; j < G.numEdges; j++) {
        for (int k = j; k < G.numEdges; k++) {
            if (isLegal(G.arc[j][k])) {
                Edge tmp;
                  
                tmp.begin = j;
                tmp.end = k;
                tmp.weight = G.arc[j][k];
                edges.push_back(tmp);
            }
        }
    }
    
    sort(edges.begin(), edges.end(), compare);

    for (Edge edge : edges) {
        n = find(parents, edge.begin);
        m = find(parents, edge.end);

        if (n != m) {
            parents[n] = m;
            printf("(%d, %d) %d\n", edge.begin, edge.end, edge.weight);
        }
   }
}



typedef int pathMatrix[MAXVEX]; // 存储最短路径下标
typedef int shortPathTable[MAXVEX]; // 存储到各点最短路径的权值和
// 求网G的v0顶点到其余顶点v最短路径P[v]及带权长度D[v]
void shortestPath_Dijkstra(MGraph G, int v0, pathMatrix *P, shortPathTable *D) {
    int v, w, k, min;
    int final[MAXVEX];
    for (v = 0; v < G.numVertexes; v++) {
        final[v] = 0;
        (*D)[v] = G.arc[v0][v];
        (*P)[v] = v0; // 这是关键 初始化成v0
    }
    (*D)[v0] = 0;
    final[v0] = 1;

    for (v = 1; v < G.numVertexes; v++) {
        min = INFINITY;
        for (w = 0; w < G.numVertexes; w++) {
            if (!final[w] && (*D)[w] < min) {
                k = w;
                min = (*D)[w];
            }
        }
        final[k] = 1;
        for (w = 0; w < G.numVertexes; w++) {
            if (!final[w] && (min+G.arc[k][w] < (*D)[w])) {
                (*D)[w] = min + G.arc[k][w];
                (*P)[w] = k;
            }
        }
    }
}
 //                                             1      0
void ShortestPathBetweenTwoCites(MGraph G, int v0, int v) {
    pathMatrix matrix;
    shortPathTable table;
    shortestPath_Dijkstra(G, v0, &matrix, &table);

    int a = v;
    printf("v%d到v%d的最短路径为:", v0, v);
    while (a != v0) {
        printf("v%d<-", a);
        a = matrix[a];
    }
    printf("v%d\n", a);
    printf("路径长度为:%d\n", table[v]);
}

void clbf() {
    while (getchar() != '\n')
        continue;
}

int main() {
    MGraph G;
    pathMatrix matrix;
    shortPathTable table;

    int option;
    while (1) {
        printf("选项\n");
        printf("(1)输入城市信息\n");
        printf("(2)打印城市信息和城市之间的直接可达距离\n");
        printf("(3)计算任意两个城市之间的最短路径\n");
        printf("(4)计算该网的最小生成树\n");
        printf("(5)退出\n");
        
        char ch1;
        while (scanf("%d", &option) == 0 || option < 1 || option > 5 || (ch1 = getchar()) != '\n') {
            printf("请输入从1到4的任意一个整数!\n");
            clbf();
        }
  
        if (5 == option)
            break;

        switch (option) {
            case 1:
                createMGraph(&G);
                break;
            case 2:
                printInfo(G);
                break;
            case 3:
                printf("请输入起点城市序号和终点城市序号(用空格相隔)\n");
                int s, d;
                scanf("%d %d", &s, &d);
                ShortestPathBetweenTwoCites(G, s, d);
                break;
            case 4:
            
                printf("最小生成树:(普利姆)\n");
                miniSpanTree_Prim(G);
                printf("\n最小生成树:(克鲁斯卡尔)\n");
                miniSpanTree_Kruscal(G);
                printf("----------------------\n");
                
        }   
    }
    
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值