HFUT《算法与数据结构》实验报告(CE专业,非CS)


这里给出的代码够完成实验了,一些简单的、书上的代码省去,如果想要完整的源码请点击: 算法与数据结构实验代码合集下载。

实验一

一、实验目的和要求∶

  1. 理解线性表的链式存储结构。
  2. 熟练掌握动态链表结构及有关算法的设计。
  3. 根据具体问题的需要,设计出合理的表示数据的链表结构,并设计相关算法。
  4. 理解单循环链表及双循环链表的特点,掌握这两种结构的算法设计。

二、实验任务∶

  1. 在一个递增有序的链表L中插入一个值为x的元素,并保持其递增有序特性。
// 第一题 
void list::insert1(elementtype x) { 
    node *u, *P; 
    P = head; 
    while (P->next != NULL && P->next->data < x)   //搜索插入位置 
        P = P->next; 
    if (P->next == NULL || P->next->data > x) {  // 找到了位置 
        u = new node; 
        u->data = x; 
        u->next = P->next;  //插入新结点 
        P->next = u; 
        count++; 
    } 
}

 
int main() { 
    list l; 
    int x; 
    cout << "创建一个链表(输入‘-1’结束):" << endl; 
    l.create2(); 
    cout << "输入要插入的数(输入‘-1’结束):" << endl; 
    cin >> x; 
    while (x != -1) { 
        l.insert1(x); 
        cin >> x; 
    } 
    l.display(); 
}

在这里插入图片描述
在这里插入图片描述
2. 将单链表L中的奇数项和偶数项结点分解开,并分别连成一个带头结点的单链表,然后再将这两个新链表同时输出在屏幕上,并保留原链表的显示结果,以便对照求解结果。

// 第二题
void list::divide(list &B, list &C) { 
    node *pa = head->next; 
    node *pb = B.get_head(); 
    node *pc = C.get_head(); 
    int i = 0; 
    while (pa != NULL){ 
        node *u = new node;  // u需要在循环里初始化 
        u->data = pa->data; 
        if (i % 2 == 0) { 
            pb->next = u; 
            pb = pb->next; 
        } else { 
            pc->next = u; 
            pc = pc->next; 
        } 
        pb->next = NULL; 
        pc->next = NULL; 
        i++; 
        pa = pa->next; 
    } 
} 
 
int main() { 
    list A, B, C; 
    A.create2(); 
    A.divide(B, C); 
    cout << "原表: "; 
    A.display(); 
    cout << "奇数表: "; 
    B.display(); 
    cout << "偶数表: "; 
    C.display(); 
}

在这里插入图片描述
在这里插入图片描述
3. 递增有序单链表A和B表示两个集合,求解C=A∪B。

// 第三题
void list::unionset(list A, list B, list &C) { 
    cout << "求并集" << endl; 
    node *Pa, *Pb, *Rc; 
    Rc = C.get_head(); 
    Pa = A.get_head()->next; 
    Pb = B.get_head()->next; 
    while (Pa != NULL && Pb != NULL) { 
        if (Pa->data < Pb->data) { 
            count++; 
            node *u = new node; 
            u->data = Pa->data; 
            Rc->next = u; 
            Rc = u; 
            Pa = Pa->next; 
        } 
        else if (Pa->data > Pb->data) { 
            count++; 
            node *u = new node; 
            u->data = Pb->data; 
            Rc->next = u; 
            Rc = u; 
            Pb = Pb->next; 
        } 
        else { 
            count++; 
            node *u = new node; 
            u->data = Pa->data; 
            Rc->next = u; 
            Rc = u; 
            Pa = Pa->next; 
            Pb = Pb->next; 
        } 
    } 
    while (Pa != NULL) { 
        count++; 
        node *u = new node; 
        u->data = Pa->data; 
        Rc->next = u; 
        Rc = u; 
        Pa = Pa->next; 
    } 
    while (Pb != NULL) { 
        count++; 
        node *u = new node; 
        u->data = Pb->data; 
        Rc->next = u; 
        Rc = u; 
        Pb = Pb->next; 
    } 
    Rc->next = NULL; 
} 
 
int main() { 
    list A, B, C; 
 
    cout << "创建一个链表(输入‘-1’结束):" << endl; 
    A.create2(); 
    A.display(); 
    cout << "===============================" << endl; 
    B.create2(); 
    B.display(); 
    cout << "===============================" << endl; 
 
    C.unionset(A,B,C) ; 
    C.display(); 
    cout << "当前链表长度为" << C.length() << endl; 
}

在这里插入图片描述
在这里插入图片描述
4. 设计算法判断单循环链表是否每个结点的值都是偶数。

// 第四题
bool list::is_even(list L) { 
    int x; 
    for (int i = 1; i <= L.length(); i++) { 
        L.get_element(i, x); 
        if (x % 2 != 0) { 
            return false; 
        } 
    } 
    return true; 
} 
 
int main() { 
    int ins_pos; 
    elementtype ins_ele, res; 
    list l; 
 
    cout << "创建一个链表(输入‘-1’结束):" << endl; 
    l.create2(); 
    l.display(); 
    cout << "===============================" << endl; 
 
    l.is_even(l) ? cout << "当前链表全为偶数" << endl : cout << "当前链表不全为偶数" << endl; 
    cout << "===============================" << endl; 
 
    cout << "输入要插入的位置、数据:" << endl; 
    cout << "enter:"; 
    cin >> ins_pos >> ins_ele; 
    while (ins_ele != -1) { 
        l.insert(ins_pos, ins_ele); 
        cin >> ins_ele; 
    } 
    l.display(); 
    cout << "===============================" << endl; 
 
    l.is_even(l) ? cout << "当前链表全为偶数" << endl : cout << "当前链表不全为偶数" << endl; 
    cout << "===============================" << endl; 
}

在这里插入图片描述
5. 构造一个双循环链表,并判断它是否对称。(选做)

实验二

一、实验目的和要求∶

  1. 掌握二叉树的动态链表存储结构及表示。
  2. 掌握二叉树的三种遍历算法。
  3. 运用二叉树三种遍历的方法求解有关问题。

二、实验任务∶

在这里插入图片描述

  1. 建立一棵采用二叉链表结构存储的二叉树。
    在这里插入图片描述
  2. 分别对该二叉树进行先序、中序和后序遍历。
    在这里插入图片描述
  3. 求二叉树的高度。
    在这里插入图片描述
  4. 求二叉树中叶子结点的数目。
    在这里插入图片描述
  5. 按中序次序输出二叉树中各结点的值及其所对应的层次数。
    在这里插入图片描述
  6. 复制一棵二叉树T到T1。
    在这里插入图片描述
  7. 交换二叉树中每个结点的左右孩子指针的值。
    在这里插入图片描述

代码

// 任务1:A B C # D # # E # F # # G H # # I # # 
void BinaryTree::CreateBinaryTree(bnode *&T) { 
    char ch; 
    cin >> ch; 
    if (ch == '#') T = NULL; 
    else { 
        T = new bnode; 
        T->data = ch; 
        CreateBinaryTree(T->lchild); 
        CreateBinaryTree(T->rchild); 
    } 
} 
 
// 任务2:先序 
void BinaryTree::preorder(bnode *T) { 
    if (T != NULL) { 
        visit(T); 
        preorder(T->lchild); 
        preorder(T->rchild); 
    } 
} 
 
// 任务2:中序 
void BinaryTree::inorder(bnode *T) { 
    if (T != NULL) { 
        inorder(T->lchild); 
        visit(T); 
        inorder(T->rchild); 
    } 
} 
 
// 任务2:后序 
void BinaryTree::postorder(bnode *T) { 
    if (T != NULL) { 
        postorder(T->lchild); 
        postorder(T->rchild); 
        visit(T); 
    } 
} 
 
// 前序遍历输出 
void BinaryTree::preTraverse(bnode *T) { 
    if (T) { 
        cout << T->data << " "; 
        preTraverse(T->lchild); 
        preTraverse(T->rchild); 
    } 
} 
 
// 任务3:求二叉树的高度 
int BinaryTree::high(bnode *T) { 
    if (T == NULL) return (0); 
    else return max(high(T->lchild), high(T->rchild)) + 1; 
} 
 
// 任务4:求二叉树中叶子结点的数目 
int BinaryTree::leaf(bnode *T) { 
    if (T == NULL) 
        return 0; 
    if (T->lchild == NULL && T->rchild == NULL) 
        return 1; 
    return leaf(T->lchild) + leaf(T->rchild); 
} 
 
// 任务5:中序输出二叉树中各结点的值及其所对应的层次数 
void BinaryTree::in_data_level(bnode *T, int n) { 
    if (T != NULL) { 
        in_data_level(T->lchild, n + 1); 
        cout << "节点值:" << T->data << ",该节点层次:" << n << endl; 
        in_data_level(T->rchild, n + 1); 
    } 
} 
 
// 任务6:复制一棵二叉树T到T1 
void BinaryTree::copy(bnode *T, bnode *&S) { 
    if (T != NULL) { 
        S = new bnode(); 
        S->data = T->data; 
        copy(T->lchild, S->lchild); 
        copy(T->rchild, S->rchild); 
    } 
} 
 
// 任务7:交换二叉树中每个结点的左右孩子指针的值 
void BinaryTree::NodeSwap(bnode *T) { 
    // 此算法根据二叉树先序遍历算法改造而来 
    if (T != NULL) { 
        // 如果T的左孩子和右孩子都不空 
        if (T->lchild != NULL && T->rchild != NULL) { 
            //将"交换二叉树每个结点的左孩子和右孩子"转换为"交换二叉树每个结点的左孩子的数据域和右孩子的指针域". 
            bnode *t = T->lchild; 
            T->lchild = T->rchild; 
            T->rchild = t; 
        } else if (T->lchild != NULL && T->rchild == NULL) {  // 如果T的左孩子不空且右孩子为空 
            //将T的左子树变为右子树 
            T->rchild = T->lchild; 
            T->lchild = NULL; 
        } else if (T->lchild == NULL && T->rchild != NULL) {  // 如果T的左孩子为空且右孩子不为空 
            //将T的右子树变为左子树 
            T->lchild = T->rchild; 
            T->rchild = NULL; 
        } else {  //如果T的左孩子和右孩子都为空 
            // 空操作 
        } 
        NodeSwap(T->lchild); 
        NodeSwap(T->rchild); 
    } 
} 
 
int main() { 
    BinaryTree b,copy; 
    int x; 
    int level = 1; 
    bnode *broot = b.get_root(); 
    bnode *copyroot = copy.get_root(); 
    cout << "1.创建一个先序二叉树(输入#为空):" << endl; 
    b.CreateBinaryTree(); 
    cout << "2.先序、中序、后序遍历" << endl; 
    cout << "3.二叉树高度" << endl; 
    cout << "4.二叉树中叶子节点数" << endl; 
    cout << "5.中序输出二叉树中各结点的值及其所对应的层次数:" << endl; 
    cout << "6.复制一棵二叉树T到T1" << endl; 
    cout << "7.交换二叉树中每个结点的左右孩子指针的值:" << endl; 
    cout << "输入你的选择(输入-1退出):"; 
    cin >> x; 
    while (x != -1) { 
        switch (x) { 
            case 2: 
                cout << "先序遍历为:"; 
                b.preorder(); 
                cout << endl; 
                cout << "中序遍历为:"; 
                b.inorder(); 
                cout << endl; 
                cout << "后序遍历为:"; 
                b.postorder(); 
                cout << endl; 
                break; 
            case 3: 
                cout << "树的高度为:"; 
                cout << b.high(b.get_root()) << endl; 
                break; 
            case 4: 
                cout << "叶子结点数为:"; 
                cout << b.leaf(b.get_root()) << endl; 
                break; 
            case 5: 
                cout << "中序输出二叉树中各结点的值及其所对应的层次数:"<< endl; 
                b.in_data_level(b.get_root(),level); 
                break; 
            case 6: 
                cout << "复制一棵二叉树T到T1:"<< endl; 
                b.copy(b.get_root(), copyroot); 
                cout << "复制得到的新树的前序遍历为:"; 
                copy.preTraverse(copyroot); 
                break; 
            case 7: 
                cout << "交换二叉树中每个结点的左右孩子指针的值:" << endl; 
                b.NodeSwap(b.get_root()); 
                cout << "交换后的二叉树先序遍历为:"; 
                b.preorder(); 
                cout << endl ; 
                cout << "交换后的二叉树中序遍历为:"; 
                b.inorder(); 
                cout << endl ; 
                cout << "交换后的二叉树后序遍历为:"; 
                b.postorder(); 
                cout << endl ; 
                break; 
        } 
        cout << endl; 
        cout << "请继续选择(输入-1退出):"; 
        cin >> x; 
    } 
}

在这里插入图片描述
在这里插入图片描述

实验三

一、实验目的和要求∶

  1. 掌握图的基本概念。
  2. 掌握图的存储结构的设计与实现,基本运算的实现。
  3. 掌握图的两种遍历算法,以及遍历算法的应用

二、实验任务∶

在这里插入图片描述

  1. 分别以邻接矩阵和邻接表的存储结构建立图。
  2. 对图进行深度优先遍历。
  3. 求图中边(或弧)的数目。
  4. 判断图中的一个顶点是否为关节点。
  5. 判断一个有向图是不是一棵有向树。(任意一个顶点可能是根)
  6. 求顶点0到图中其余每个顶点的最短路径(以边数计算)。(选做)

在这里插入图片描述

代码

// 建立邻接表(无向图) 
void graph::createadj() { 
    int i, j, k; 
    ednode *s; 
    // 输入顶点个数 
    cout << "请输入顶点个数:"; 
    cin >> CurrentVertex; 
    cout<<"请输入各顶点的值:"<<endl; 
    for (k = 0; k < CurrentVertex; k++) { 
//        cout << "输入第" << k + 1 << "个顶点的值:"; 
        cin >> vertex[k].verdata; 
    } 
    cout << "请输入边(输入-1 -1结束):" ; 
    cin >> i >> j; 
    while (i != -1) { 
        s = new ednode; 
        s->adjvex = j; 
        s->nextadj = vertex[i].firstadj; 
        //在顶点为 i 的邻接表中插入顶点为 j 的邻接点 
        vertex[i].firstadj = s; 
        s->adjvex = i; 
        s->nextadj = vertex[j].firstadj; 
        //在顶点为 j 的邻接表中插入顶点为 i 的邻接点 
        vertex[j].firstadj = s; 
        cout << "请输入边(输入-1 -1结束):" ; 
        cin >> i >> j; 
    } 
} 
 
int main() { 
    graph G; 
    cout << "用邻接表存储建立图:" << endl; 
    G.createadj(); 
    cout << endl; 
    cout << "对图的深度优先遍历:" << endl; 
    G.Travel_DFS(); 
    cout << endl; 
}

在这里插入图片描述

// 建立邻接矩阵(无向图) 
void graph::createadj() { 
    int i, j, k; 
    cout << "请输入顶点个数:"; 
    cin >> CurrentVertex; 
    cout << "请输入各顶点的值:" << endl; 
    for (k = 0; k < CurrentVertex; k++) 
        cin >> vertex[k]; 
    cout << "请输入边(输入-1 -1结束):"; 
    cin >> i >> j; 
    while (i != -1) { 
        edge[i][j] = edge[j][i] = 1; 
        cout << "请输入边(输入-1 -1结束):"; 
        cin >> i >> j; 
    } 
} 
 // 从 v 点出发进行深度优先遍历 
void graph::dfs(int v) { 
    int w; 
    visit(v); 
    visited[v] = true; 
    w = firstadj(v); 
    while (w != -1) { 
        if (!visited[w]) 
            dfs(w); 
        w = nextadj(v, w); 
    } 
} 
 
// 任务2:深度优先遍历图 
void graph::Travel_DFS() { 
    int i; 
    for (i = 0; i < CurrentVertex; i++) 
        visited[i] = false; 
    for (i = 0; i < CurrentVertex; i++) 
        if (!visited[i]) 
            dfs(i); 
}
// 任务3:求图中边(或弧)的数目 
void graph::beforeedge(int v) { 
    int w; 
    visited[v] = true; 
    w = firstadj(v); 
    while (w != -1) { 
        E++; 
        if (!visited[w]) beforeedge(w); 
        w = nextadj(v, w); 
    } 
} 
 
int graph::edgenum() { 
    E = 0; 
    for (int i = 0; i < CurrentVertex; i++) 
        visited[i] = false; 
    for (int i = 0; i < CurrentVertex; i++) 
        if (visited[i] == false) 
            beforeedge(i); 
    return E / 2; 
} 
 
// 任务4:判断图中的一个顶点是否为关节点 
/* 
 * 关节点是指在某图中,如果删除顶点V以及V相关的边后, 
 * 图的一个连通分量分割为两个或两个以上的连通分量, 
 * 则称顶点V为该图的一个关节点。 
 * */ 
int graph::numofGC() { 
    int i; 
    int k = 0;  // k 用于连通分量的计数 
    for (i = 0; i < CurrentVertex; i++) 
        visited[i] = false; 
    for (i = 0; i < CurrentVertex; i++) 
        if (visited[i] == false) { 
            k++;  // 用 k 来累计连通分量个数 
            beforeedge(i); 
        } 
    return k; 
} 
 
// 删除一个顶点的边 
bool graph::deleteside(elementtype v){ 
    int i; 
    for(i = 0;i < CurrentVertex;i++){ 
        if(v < 0 || v >= CurrentVertex) 
            return false; 
        edge[v][i] = edge[i][v] = 0; 
    } 
    return true; 
} 
 
// 任务5:判断一个有向图是不是一棵树(任意一个顶点可能是根) 
/* 
 * 判断有向图是不是有向树: 
 * 1.有且仅有一个节点,入度为0,即为根 
 * 2.其他节点,入度皆为1 
 * 3.从根开始广度搜索 所遍历的节点数应当与有向图中的节点数相等 
 * */ 
void graph::istree() { 
    int a, b, c; 
    a = b = c = 0; 
    for (int i = 0; i < CurrentVertex; i++) { 
        for (int j = 0; j < CurrentVertex; j++) { 
            if (edge[j][i] == 1) 
                a++; 
        } 
        if (a == 0) b++; 
        if (a == 1) c++; 
        a = 0; 
    } 
    if (b == 1 && c == CurrentVertex - 1) 
        cout << "该有向图是有向树" << endl; 
    else 
        cout << "该有向图不是有向树" << endl; 
} 
 
int main() { 
    graph g,g1; 
    int v,x,beforedel,afterdel,diff; 
    cout << "1.建立图:" << endl; 
    g.createadj(); 
    cout << "2.对图深度优先遍历" << endl; 
    cout << "3.求图中边(或弧)的数目" << endl; 
    cout << "4.判断图中的一个顶点是否为关节点" << endl; 
    cout << "5.判断一个有向图是不是一棵树(任意一个顶点可能是根)" << endl; 
    cout << "输入你的选择(输入-1退出):"; 
    cin >> x; 
    while (x != -1) { 
        switch (x) { 
            case 2: 
                cout << "本图的深度遍历为:"; 
                g.Travel_DFS(); 
                cout << endl; 
                break; 
            case 3: 
                cout << "图中边的数目为:" << g.edgenum() << endl; 
                break; 
            case 4: 
                g1 = g; 
                cout << "输入要判断的顶点:" << endl; 
                cin >> v; 
                beforedel = g1.numofGC(); 
                cout << "删除顶点" << v << "的边前,连通分量有" << beforedel << "个" << endl; 
                g1.deleteside(v); 
                afterdel = g1.numofGC(); 
                cout << "删除顶点" << v << "的边后,连通分量有" << afterdel << "个" << endl; 
                diff = afterdel - beforedel; 
                if (diff > 1) 
                    cout << "顶点" << v << "是关节点" << endl; 
                else if ((diff == 0) || (diff == 1)) 
                    cout << "顶点" << v << "不是关节点" << endl; 
                else 
                    cout << "error!" << endl; 
                break; 
            case 5: 
                cout << "判断一个有向图是不是一棵树:" <<  endl; 
                g.istree(); 
                break; 
        } 
        cout << endl; 
        cout << "请继续选择(输入-1退出):"; 
        cin >> x; 
    } 
}

在这里插入图片描述
在这里插入图片描述

数据结构查找实验代码 (1) 对下列数据表,分别采用二分查找算法实现查找,给出查找过程依次所比较的元素(的下标),并以二分查找的判定树来解释。 第一组测试数据: 数据表为 (1,2,3,4,6,7,8,9,10,11,12,13,17,18,19,20,24,25,26,30,35,40,45,50,,100) 查找的元素分别为: 2,8,20, 30,50,5,15,33,110 第二组数据: 数据表为 (2,3,5,7,8,10,12,15,18,20,22,25,30,35,40,45,50,55,60, 80,100) 查找的元素分别为: 22,8,80,3,100,1,13,120 (2) 设计出在二叉排序树中插入结点的算法,在此基础上实现构建二叉排序树的算法。 测试数据:构建二叉排序树的输入序列如下: 第一组数据: 100,150,120,50,70,60,80,170,180,160,110,30,40,35,175 第二组数据: 100,70,60,80,150,120,50,160,30,40,170,180,175,35 (3) 设计算法在二叉排序树中查找指定值的结点。 测试数据:在任务中第一组测试数据所构造的二叉排序树中,分别查找下列元素: 150,70,160,190,10,55,175 (4) 设计算法在二叉排序树中删除特定值的结点。 测试数据:在任务(1)中第一组测试数据所构造的二叉排序树中,分别删除下列元素:30,150,100 (5) 已知整型数组A[1..26]递增有序,设计算法以构造一棵平衡的二叉排序树来存放该数组中的所有元素。 测试数据:数组元素分别为: 第一组数据: (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26) 第二组数据: (1,3,6,10,15,21,28,36,45,55,66,78,91,105,120,136,153,171,190,210,231,253,277,302,328)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值