数据结构基础笔记(一)【严蔚敏】


广义表

广义表相关概念:

◆ a1(表中第一个元素)称为表头

◆ 其余元素组成的子表称为表尾;(a2,a3,…,an)

◆ 广义表中所包含的元素(包括原子和子表)的个数称为表的长度。

◆ 广义表中括号的最大层数称为表深 (度)。

根据对表头、表尾的定义,任何一个非空广义表的表头可以是原子,也可以是子表, 而表尾必定是广义表。

只要广义表非空,都是由表头和表尾组成,即一个确定的表头和表尾就唯一确定一个广义表。

广义表数据结点定义:

typedef struct GLNode
{
    int   tag ;     /*  标志域,为1:表结点;为0 :原子结点  */
    union
    {  elemtype value;     /* 原子结点的值域  */
    struct
        {  struct GLNode  *hp , *tp ;
         }ptr ;   /*  ptr和atom两成员共用  */
    }Gdata ;
} GLNode ;      /* 广义表结点类型  */

二叉树

满二叉树(Full Binary Tree)

一棵深度为k且有2^k-1个结点的二叉树称为满二叉树。

完全二叉树(Complete Binary Tree)

如果深度为k,由n个结点的二叉树,当且仅当其每一个结点都与深度为k的满二叉树中编号从1到n的结点一一对应,该二叉树称为完全二叉树。

完全二叉树是满二叉树的一部分,而满二叉树是完全二叉树的特例。

####遍历

  • 前序非递归遍历

    思路:

    1).访问当前结点,用栈暂存当前结点的右结点【如果不为空】;

    2).如果当前结点的左结点不为空,则进入继续访问,否则从栈取结点访问,即返回1继续,如果栈为空则结束遍历;

    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> ans;
        if (!root) return ans;
        stack<TreeNode*> stk_tree;
        while (1){
            ans.push_back(root->val);
            if (root->right) stk_tree.push(root->right);
            if (root->left) root = root->left;
            else if (stk_tree.empty()) break;
            else {
                root = stk_tree.top(); stk_tree.pop();
            }
        }
        return ans;
    }
  • 中序非递归遍历

    思路:

    1).若p不为空,p进栈,p=p->Lchild;

    2).否则(即p为空),退栈到p,访问p所指向的结点;【栈为空则结束】

    3).如果p的右结点不为空,p=p->Rchild ,转1;

    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> ans;
        if (!root) return ans;
        stack<TreeNode*> s;
        while (root) {
            s.push(root);
            root = root->left;
        }
        while (!s.empty()) {
            TreeNode * t = s.top();
            s.pop();
            ans.push_back(t->val);
            if (t->right) {
                t = t->right;
                while (t){
                    s.push(t);
                    t = t->left;
                }
            }
        }
        return ans;
    }
  • 后序非递归遍历

    思路:

    这里使用flag的栈对应表示结点属性,如果flag=1表示结点为父节点,进栈后再次出栈时可以直接访问;而如果flag=0表示该节点是右子节点,需要将该节点的子节点入栈,同时它本身的flag变为1.

    1).若p不为空,p进栈【flag=1】,同时如果p的右结点不为空,右结点进栈【flag=0】,进入p=p->left;

    2).从栈中取值,如果flag=1,说明该节点的子节点已经访问结束,该节点可以访问;否则进入1继续。【栈为空结束】

    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> ans;
        if (!root) return ans;
        stack<TreeNode*> stk_tree;
        stack<int> stk_flag;
        while (root){
            stk_tree.push(root);
            stk_flag.push(1);
            if (root->right) {
                stk_tree.push(root->right); stk_flag.push(0);
            }
            root = root->left;
        }
        while (!stk_tree.empty()) {
            root = stk_tree.top(); stk_tree.pop();
            flag = stk_flag.top(); stk_flag.pop();
            if (!flag) {
                while (root){
                    stk_tree.push(root);
                    stk_flag.push(1);
                    if (root->right) {
                        stk_tree.push(root->right); stk_flag.push(0);
                    }
                    root = root->left;
                }
            }
            else {
                ans.push_back(root->val);
            }
        }
        return ans;
    }

在一条路径中,若没有重复相同的顶点,该路径称为简单路径

第一个顶点和最后一个顶点相同的路径称为回路(环)

对无向图G=(V,E),若任意vi,vj∈V,vi和vj都是连通的,则称图G是连通图,否则称为非连通图。若G是非连通图,则极大的连通子图称为G的连通分量

对有向图G=(V,E),若任意vi,vj∈V,都有以vi为起点, vj 为终点以及以vj为起点,vi为终点的有向路径,称图G是强连通图,否则称为非强连通图。若G是非强连通图,则极大的强连通子图称为G的强连通分量

最小生成树

  • 普里姆(Prim)算法

    算法思想(算法复杂度O(n^2)):

    1). 若从顶点v0出发构造,U={v0},TE={};

    2). 先找权值最小的边(u,v),其中u∈U且v∈V-U,并且子图不构成环,则U= U∪{v},TE=TE∪{(u,v)} ;

    3). 重复⑵ ,直到U=V为止。则TE中必有n-1条边, T=(U,TE)就是最小生成树。

题目链接:#1097 : 最小生成树一·Prim算法

定义一维数组保存V-U中各顶点到U中顶点具有权值最小的边【lowcost】:如果lowcost为0表示已加入到U中,否则每轮都要V-U中更新各顶点的lowcost

struct {
    int  adjvex;     /*   边所依附于U中的顶点   */
    int  lowcost;    /*   该边的权值   */
}closedge[N];
#include <stdio.h>
#include <string.h>
#define N 1002
#define INFINITY 10005;

struct {
    int  adjvex;     /*   边所依附于U中的顶点   */
    int  lowcost;    /*   该边的权值   */
}closedge[N];
int array[N][N];

int prim(int n){
    int i, j, min, v, ans = 0, idx;
    //初始化数组【默认从v0开始】
    for (i = 0; i < n; i++) {
        closedge[i].adjvex = 0;
        closedge[i].lowcost = array[i][0];
    }
    //n-1趟
    for (j = 0; j < n - 1; j++) {
        min = INFINITY;
        //找到到U的最小权值的顶点
        for (v = 0; v < n; v++) {
            if (closedge[v].lowcost != 0 && closedge[v].lowcost < min) {
                min = closedge[v].lowcost;
                idx = v;
            }
        }
        ans += min;
        closedge[idx].lowcost = 0;//将该顶点加入U中
        for (v = 0; v<n; v++)
            if (array[v][idx]<closedge[v].lowcost) {
                closedge[v].lowcost = array[v][idx];
                closedge[v].adjvex = idx;
            }  /*   修改数组closedge[n]的各个元素的值   */
    }
    return ans;
}

int main()
{
    int n, i, j;
    scanf("%d", &n);
    for (i = 0; i < n; i++)
        for (j = 0; j < n; j++)
            scanf("%d", &array[i][j]);
    printf("%d\n", prim(n));
    return 0;
}

注:prim算法稍加修改即可变为Dijkstra算法。【lowcost表示到各个顶点到给定单点的最短距离。】

  • 克鲁斯卡尔(Kruskal)算法

    思想:

    设G=(V, E)是具有n个顶点的连通网,T=(U, TE)是其最小生成树。初值:U=V,TE={} 。c

    对G中的边按权值大小从小到大依次选取。

    1). 选取权值最小的边(vi,vj),若边(vi,vj)加入到TE后形成回路,则舍弃该边(边(vi,vj) ;否则,将该边并入到TE中,即TE=TE∪{(vi,vj)} 。

    2). 重复1),直到TE中包含有n-1条边为止。

题目链接:#1098 : 最小生成树二·Kruscal算法

先将所有边排序,然后遍历判定是否边的两个顶点是否在一个集合,如果在则会形成回路,舍弃之;否则将改边加入TE。【判定两个点是否在一个集合用并查集算法】

#include<iostream>
#include<algorithm>
using namespace std;

struct edge{
    int u;
    int v;
    int len;
};

int cmp(const edge a, const edge b) {
    return a.len < b.len;
}

#define M 1000005
#define N 100005
edge e[M];
int pos[N];                         //记录各个节点在哪个集合中。

void init(int n) {
    for (int i = 1; i <= n; i++)    pos[i] = i;
}

int find(int x) {
    if (x == pos[x]) return x;
    else {
        pos[x] = find(pos[x]);
        return pos[x];
    }
}

int kruskal(int n, int m) {
    int sum = 0,count = 1;
    for (int i = 0; i < m; i++) {
        int fx = find(e[i].u);
        int fy = find(e[i].v);
        if (fx != fy) {
            sum += e[i].len;
            count++;
            if (count == n) break;
            pos[fx] = fy;
        }
    }
    return sum;
}

int main() {
    int n, m;
    while (cin >> n >> m) {
        init(n);                            //初始化并查集
        for (int i = 0; i < m; i++) cin >> e[i].u >> e[i].v >> e[i].len;
        sort(e, e + m, cmp);
        cout << kruskal(n, m) << endl;
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-01 13:20:27

数据结构基础笔记(一)【严蔚敏】的相关文章

数据结构基础笔记(二)【严蔚敏】

动态存储管理:伙伴系统 分配内存算法思想: 当程序提出大小为n的内存分配请求时,首先在可利用表中查找大小与n相匹配的子表. ◆ 若存在2^(k-1)< n ≤ 2^k-1的空闲子表结点:则将子表中的任意一个结点分配之: ◆ 若不存在2^(k-1) < n ≤ 2^k-1的空闲子表结点:则从结点大小为2^k的子表中找到一个空闲结点,将其中一半分配给程序,剩余的一半插入到结点大小为2k-1的子表中. 注:在进行大小为n(2^(k-i-1) < n ≤ 2^(k-i)-1,i=1,2,-,k-

树和二叉树-第6章-《数据结构题集》习题解析-严蔚敏吴伟民版

习题集解析部分 第6章 树和二叉树 ——<数据结构题集>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑       相关测试数据下载  链接? 数据包       本习题文档的存放目录:数据结构\▼配套习题解析\▼06 树和二叉树  

数组和广义表-第5章-《数据结构题集》答案解析-严蔚敏吴伟民版

习题集解析部分 第5章 数组和广义表 ——<数据结构题集>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑       本习题文档的存放目录:数据结构\▼配套习题解析\▼05 数组和广义表       文档中源码的存放目录:数据结构\▼配

图-第7章-《数据结构题集》习题解析-严蔚敏吴伟民版

习题集解析部分 第7章 图 ——<数据结构题集>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑       相关测试数据下载  链接? 数据包       本习题文档的存放目录:数据结构\▼配套习题解析\▼07 图       文档中源

串-第4章-《数据结构题集》答案解析-严蔚敏吴伟民版

习题集解析部分 第4章 串 ——<数据结构题集>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑       本习题文档的存放目录:数据结构\▼配套习题解析\▼04 串       文档中源码的存放目录:数据结构\▼配套习题解析\▼04

绪论-第1章-《数据结构题集》习题解析-严蔚敏吴伟民版

习题集解析部分 第1章  绪论 ——<数据结构题集>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑          本习题文档的存放目录:数据结构\▼配套习题解析\▼01 绪论\        文档中源码的存放目录:数据结构\▼配套习

动态存储管理-第8章-《数据结构题集》习题解析-严蔚敏吴伟民版

习题集解析部分 第8章 动态存储管理 ——<数据结构题集>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑       相关测试数据下载  链接? 数据包       本习题文档的存放目录:数据结构\▼配套习题解析\▼08 动态存储管理

外部排序-第11章-《数据结构题集》习题解析-严蔚敏吴伟民版

习题集解析部分 第11章 外部排序 ——<数据结构题集>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑       相关测试数据下载  链接? 数据包       本习题文档的存放目录:数据结构\▼配套习题解析\▼11 外部排序    

文件-第12章-《数据结构题集》习题解析-严蔚敏吴伟民版

习题集解析部分 第12章 文件 ——<数据结构题集>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑       相关测试数据下载  链接? 数据包       本习题文档的存放目录:数据结构\▼配套习题解析\▼12 文件       文