20162326 齐力锋 实验四


 实验报告
 课程:程序设计与数据结构
班级: 1623
 姓名: 齐力锋
学号:2016232 成绩: 2分 指导教师:娄嘉鹏 王志强

实验日期:11月20日

 密级:非密级
 预习程度: 已预习
 必修/选修: 必修
 实验序号: 2326

实验一 : 

  • 用邻接矩阵实现无向图(边和顶点都要保存),实现在包含添加和删除结点的方法,添加和删除边的方法,size(),isEmpty(),广度优先迭代器,深度优先迭代器
  • 给出伪代码,产品代码,测试代码(不少于5条测试)
  • 上方提交代码链接

附件提交测试截图

实验二 :

  • 用十字链表实现无向图(边和顶点都要保存),实现在包含添加和删除结点的方法,添加和删除边的方法,size(),isEmpty(),广度优先迭代器,深度优先迭代器
  • 给出伪代码,产品代码,测试代码(不少于5条测试)
  • 上方提交代码链接
  • 附件提交测试截图

实验三 :

  • 实现PP19.9
  • 给出伪代码,产品代码,测试代码(不少于5条测试)
  • 上方提交代码链接
  • 附件提交测试截图

实验过程及问题解决:

一、

首先,我思考了什么是邻接矩阵,该用怎么样的方法去实现邻接矩阵创建图。

我认为可以用一个一维数组存放图中所有顶点数据。用一个二维数组存放顶点间关系(边或着弧)的数据,这个二维数组称为邻接矩阵

基于此,我开始了实验一

//--------------------------------------------------
// 伪代码:
// 初始化"顶点数"和"边数"
// 采用已有的"图"
// 初始化"顶点"
// 初始化"边"
//替换为二维数组
//利用 printf 格式化打印
//-------------------------------------------------------      
// Writen by QLF

public class Matrix {

    private char[] DingDian;       // 顶点集合
    private int[][] LinjieMatrix;    // 邻接矩阵
    int numDingDian; //顶点数
    int numedgs;//边数

    public Matrix(char[] DingDian, char[][] edges) {

        // 初始化"顶点数"和"边数"
        this.numDingDian = DingDian.length;
        this.numedgs = edges.length;

        // 初始化"顶点"
        this.DingDian = new char[numDingDian];
        for (int i = 0; i < this.DingDian.length; i++)
            this.DingDian[i] = DingDian[i];

        // 初始化"边"
        LinjieMatrix = new int[numDingDian][numDingDian];
        for (int i = 0; i < numedgs; i++) {
            // 读取边的起始顶点和结束顶点
            int p1 = getPosition(edges[i][0]);
            int p2 = getPosition(edges[i][1]);

            LinjieMatrix[p1][p2] = 1;
            LinjieMatrix[p2][p1] = 1;
        }
        /*
     * 
     *
     * 
     *     DingDian  -- 顶点数组
     *     edges -- 边数组
     */
    }

    
    private int getPosition(char ch) {
        for(int i = 0; i< DingDian.length; i++)
            if(DingDian[i]==ch)
                return i;
        return -1;
    }


    public void print() {
        System.out.printf("Martix Graph:\n");
        for (int i = 0; i < DingDian.length; i++) {
            for (int j = 0; j < DingDian.length; j++)
                System.out.printf("%d ", LinjieMatrix[i][j]);
            System.out.printf("\n");
        }
    }
    public void addEdge(int start,int end,int len){ //在两个指定下标的节点之间添加一条边
        LinjieMatrix[start][end] = len;
        LinjieMatrix[end][start] = len;
        numedgs++;
    }

    //在2个顶点之间删除一条边

    public void removeEdge(int start,int end){    //删除两个指定下标顶点之间的边
        LinjieMatrix[start][end] = 0;
        LinjieMatrix[end][start] = 0;
        numedgs--;
    }


    public static void main(String[] args) {
        char[] vexs = {'齐', '力', '锋', '啊', 'E', 'F', 'G'};
        char[][] edges = new char[][]{
                {'齐', '锋'},
                {'齐', '啊'},
                {'齐', 'F'},
                {'力', '锋'},
                {'锋', '啊'},
                {'E', 'G'},
                {'F', 'G'}};
        Matrix pG;
//--------------------------------------------------
// 伪代码:
        // 初始化"顶点数"和"边数"
        // 采用已有的"图"
        // 初始化"顶点"
        // 初始化"边"
        //替换为二维数组
        //利用 printf 格式化打印
//-------------------------------------------------------        
        pG = new Matrix(vexs, edges);
       pG.addEdge(2,3,3);
       pG.removeEdge(3,3);
        pG.print();   // 打印图
    }
}

我的思路为:

1.初始化"顶点数"和"边数"

2.采用已有的"图"

3.初始化"顶点"

4.初始化"边"

5.替换为二维数组

6.利用 printf 格式化打印

 

我的方法简而概之就是利用一维数组存储点的信息(Char类型),二维数组描述边之间的关系。

20162326 齐力锋 实验四_第1张图片

 

 

二、

 

 

总的思想:

有向图的邻接表和逆邻接表结合起来得到的

邻接表是有缺陷的,关心了出度问题,想了解入度就必须要遍历整个图才能知道

十字链表通常是实现有向图的,这次实验要求实现无向图,虽然降低了难度,但是可供学习的资源少了,有些难度

我认为,在无向图的应用中,关注的重点是顶点的话,那么邻接表是不错的选择,但如果我们更关注的是边的操作,比如对已经访问过的边做标记,或者删除某一条边等操作,邻接表就显得不那么方便了。

20162326 齐力锋 实验四_第2张图片

/**
 * Created by 齐力锋 on 2017/11/24.
 */
/*

 * 作者:齐力锋
 * 作业为实验四2
 * vexs  --  顶点数组
 *         edges  --  边数组
伪代码和解释在每个方法旁的注释处
*/

public class OTHList {
    int Numvlen; // 顶点个数
    int Numelen; // 边个数
    VertexNode[] vertexNodeList; // 顶点数组
    EdgeNode edgeNode;


    public OTHList(char[] vexs, char[][] edges) {
       this.Numvlen = vexs.length;
        this.Numelen = edges.length;

        // 初始化顶点,建立顶点表
        vertexNodeList = new VertexNode[Numvlen];
        for (int i = 0; i < Numvlen; i++) {
            vertexNodeList[i] = new VertexNode();
            vertexNodeList[i].vertex = vexs[i];
            vertexNodeList[i].firstIn = null;
            vertexNodeList[i].firstOut = null;
        }

        // 初始化边,利用头插法建立十字链表
        for (int i = 0; i < Numelen; i++) {
            EdgeNode edgeNode1 = new EdgeNode();
            EdgeNode edgeNode2 = new EdgeNode();
            int haha = FindWhere(edges[i][0], vexs);
            int hehe = FindWhere(edges[i][1], vexs);

            edgeNode1.tailvex = haha;
            edgeNode1.headvex = hehe;
            edgeNode1.taillink = vertexNodeList[haha].firstOut;
            vertexNodeList[haha].firstOut = edgeNode1;

            edgeNode2.tailvex = haha;
            edgeNode2.headvex = hehe;
            edgeNode2.headlink = vertexNodeList[hehe].firstIn;
            vertexNodeList[hehe].firstIn = edgeNode2;

        }
    }

    /**
     *  伪代码:
     *  顶点表结点结构
     *  vertex :存储顶点信息
     *       firstIn  :入边表头指针,指向该顶点的入边表中第一个结点
     *       firstOut : 出边表头指针,指向该顶点的出边表中第一个结点
     */
    private class VertexNode {
        char vertex;
        EdgeNode firstIn;
        EdgeNode firstOut;
    }

    /**
     *  边表结点
     *  tailvex 弧起点在顶点表的下标
     *        headvex 弧终点在顶点表的下标
     *        headlink 入边表指针域,指向终点相同的下一条边
     *        taillink 边表指针域,指向起点相同的下一条边
     */
    private class EdgeNode {
        int tailvex;
        int headvex;
        EdgeNode headlink;
        EdgeNode taillink;
    }

    /**
     *  返回char的位置
     */
    private int FindWhere(char ch, char[] vexs) {
        for (int i = 0; i < Numvlen; i++)
            if (vexs[i] == ch)
                return i;
        return -1;
    }

    /**
     *  打印邻接表   注:这里参考了一些网上的代码(有些不太会)
     */
    public void print() {
        System.out.printf("邻接表:\n");
        for (int i = 0; i < Numvlen; i++) {
            System.out.print(vertexNodeList[i].vertex + "-->");
            if (vertexNodeList[i].firstOut != null) {
                EdgeNode mEdgeNode = new EdgeNode();
                mEdgeNode = vertexNodeList[i].firstOut;
                System.out.print(mEdgeNode.headvex);
                while (mEdgeNode.taillink != null) {
                    mEdgeNode = mEdgeNode.taillink;
                    System.out.print(mEdgeNode.headvex);
                }
                System.out.print("\n");
            } else {
                System.out.print("\n");
            }
        }

        System.out.print("----------\n");

        System.out.printf("逆邻接表:\n");
        for (int i = 0; i < Numvlen; i++) {
            System.out.print(vertexNodeList[i].vertex + "<--");
            if (vertexNodeList[i].firstIn != null) {
                EdgeNode mEdgeNode = new EdgeNode();
                mEdgeNode = vertexNodeList[i].firstIn;
                System.out.print(mEdgeNode.tailvex);
                while (mEdgeNode.headlink != null) {
                    mEdgeNode = mEdgeNode.headlink;
                    System.out.print(mEdgeNode.tailvex);
                }
                System.out.print("\n");
            } else {
                System.out.print("\n");
            }
        }
    }
    public boolean removeSide(Object A,Object B) throws Exception {
        boolean result = false;
        int num1 = -1,num2 = -1;
        for(int i=0;i){
            if(vertexNodeList[i].equals(A))
                num1 = i;
            else if(vertexNodeList[i].equals(B))
                num2 = i;
        }
        if(num1!=-1 && num2 != -1){
           
            result = true;
        }
        return result;
    }
    public boolean removeNode(Object m){
        int A = -1;
        boolean result = false;
        for(int i=0;i){
            if(vertexNodeList[i].equals(m))
                A = i;
        }

        if(A!=-1)
            result = true;
        return result;
    }
    public boolean isEmpty(){
        return (this.size()==0);
    }
    public int size(){
        return vertexNodeList.length;
    }
    /**
     * 主函数
     */
    public static void main(String args[]) {
        // 顶点数组
        char[] vexs = {
                '齐', '力', '锋', '陕'
        };
        // 边数组
        char[][] edges = new char[][] {
                {
                        '齐', '力'
                }, {
                '齐', '锋'
        }, {
                '齐', '陕'
        }, {
                '力', '陕'
        }, {
                '锋', '陕'
        }
        };

        OTHList listUDG = new OTHList(vexs, edges);
        listUDG.print();
    }
}

我的变量的解释:

tailvex是指弧起点在顶点的下标,

headvex是指弧终点在顶点表中的下标,

headlink是指入边表指针域,指向终点相同的一下条边

taillink是指出边表指针域,指向起点相同的下一条边。

顶点依然是一个一维数组,存储他的信息

其实这里可以采用链式存储结构,LinkedList,这样会方便很多,直接用remove,size,isEmpty等方法

你可能感兴趣的:(20162326 齐力锋 实验四)