第六章 数据结构相关知识点总结

一、树的数据结构

//使用数组+下标的方式实现二叉树。  
const int root=1;  
void newtree()  
{   
    left[root]=right[root]=0;  
    have_value[root]=false;  
    cnt=root;   
}   
int newnode()  
{  
    int u=++cnt;  
    left[u]=right[u]=0;  
    have_value[u]=false;  
    return u;  
}  
//使用Node
struct Node  
{  
    bool have_value;  
    int v;  
    Node *left,*right;  
    Node():have_value(false),left(NULL),right(NULL){}  
};  
bool failed;  
Node* root;  
char s[maxn];   
//树节点的数据结构   
  
//增加节点   
Node* newnode()  
{  
    return new Node();  
}  
//构建树   
void addnode(int v,char* s)  
{  
    int n = strlen(s);  
    Node* u = root;   
    for(int i=0;i<n;i++)  
    {  
        if(s[i]=='L')  
        {  
            if(u->left==NULL) u->left = newnode();  
            u=u->left;  
        }  
        else if(s[i]=='R')  
        {  
            if(u->right==NULL) u->right = newnode();  
            u=u->right;    
        }  
    }  
    if(u->have_value) failed=true;  
    u->v=v;  
    u->have_value=true;    
}  

实际上很多时候,我们直接使用left和right数组直接时使用。

const int root=0;left[root]和right[root]进行赋值,这样使用的不是动态数组,所以存储开销要计算好。因为很多空余是没有存储的。

二、树的BFS和DFS

在进行BFS的时候一般使用queue进行辅助遍历。
bool bfs(vector<int> &ans)  
{  
    queue<Node*> q;  
    ans.clear();  
    q.push(root);  
    while(!q.empty())  
    {  
        Node* u=q.front();q.pop();  
        if(!u->have_value) return false;  
        ans.push_back(u->v);  
        if(u->left!=NULL) q.push(u->left);  
        if(u->right!=NULL)q.push(u->right);  
    }  
    return true;  
}   
使用DFS的时候,根据根的位置不同分为不同的遍历方式。总的而言,DFS都是递归遍历形式。
void postorder(int root)  
{  
    // cout<<value; 先序遍历
    if(lch[root]!=-1) postorder(lch[root]);  
// cout<<value; 中序遍历
    if(rch[root]!=-1) postorder(rch[root]);  
    //cout<<value;  后序遍历
        }


三、 图的数据结构

图的数据结构一般采用邻居矩阵的形式,只有特别大的才考虑邻接表的形式进行存储。


四、图的BFS和DFS

采用dfs进行递归遍历的时候,一般配有visit数组来表示是否访问的点已经被访问。
void dfs(int r,int c,int id)  
{  
    if(r<0||r>=m||c<0||c>=n) return;  
    //行和列越界判断   
    if(idx[r][c]>0||pic[r][c]!='@') return;  
    // idx[r][c]>0 表示已经被遍历过。   
    // 节约时间,快速返回。   
    idx[r][c]=id;  
    for(int dr=-1;dr<=1;dr++)  
    //dc和dr表示可以朝上下左右移动   
        for(int dc=-1;dc<=1;dc++)  
            if(dr!=0||dc!=0) dfs(r+dr,c+dc,id);  
            //dr和dc不能同时为0,如果同时为0,则原地不动。   
}   
采用bfs进行遍历的时候,同样也要使用队列进行辅助。采用循环判断队列是否为空的方式进行。
void solve()  
{  
    queue<Node> q;  
    memset(d,-1,sizeof(d));  
    Node u(r1,c1,dir);//起点   
    d[u.r][u.c][u.dir]=0;  
    //初始状态到(r,c,dir)的最短路径   
    q.push(u);//然后将u压入栈内   
    while(!q.empty())//层次遍历是否结束   
    {  
        Node u = q.front();  
        q.pop();  
        if(u.r==r2 && u.c==c2)//表示如果u已经到达终点   
        {  
            printf_ans(u);//输出   
            return;  
        }  
        for(int i=0;i<3;i++)//3个方向   
        {  
            Node v = walk(u,i);  
            if(has_edge[u.r][u.c][u.dir][i]&&d[v.r][v.c][v.dir]<0)  
            //has_edge表示这种前进方式是否能够进入。d[v.r][v.c][v.dir]表示还没有到达这个点.  
            {  
                d[v.r][v.c][v.dir]=d[u.r][u.c][u.dir]+1;  
                p[v.r][v.c][v.dir]=u;  
                q.push(v);  
            }   
        }  
    }  
    printf("  No Solution Possible\n");  
}  

五、拓扑排序

#include<cstdio>  
#include<cstring>  
const int maxn=100+5;  
//c数组,0表示从未访问过,1表示已经访问并递归过它的子孙。  
//-1表示正在访问。  
int c[maxn];   
int topo[maxn],t,n;  
int G[maxn][maxn];   
bool dfs(int u)  
{  
    c[u]=-1;  
    for(int v=1;v<=n;v++)  
    {  
        if(G[u][v])  
        //采用邻接矩阵存储图,表示u有指向v的边,表示u完成后v才能完成。   
        {  
            if(c[v]<0) return false;//判断是否有环的存在   
            else if (!c[v]&&!dfs(v)) return false;  
            //如果v已经被访问过,则退出。  
            //如果没有访问,就进行深度遍历,进行访问。   
        }  
          
    }  
    c[u]=1;topo[--t]=u;  
    return true;  
}  
bool toposort()  
{  
    t=n;  
    memset(c,0,sizeof(c));  
    for(int u=1;u<=n;u++)  
    {  
        if(!c[u])//没有进行访问的才进行访问   
        {  
            if(!dfs(u)) return false;  
        }  
    }  
    return true;  
}  
      
int main()  
{  
    //freopen("datain.txt","r",stdin);  
    //freopen("dataout.txt","w",stdout);  
    int m;  
    while(scanf("%d%d",&n,&m)&&n)  
    {  
        memset(G,0,sizeof(G));  
        while(m--)  
        {  
            int i,j;  
            scanf("%d%d",&i,&j);  
            G[i][j]=1;  
        }     
        toposort();  
        for(int i=0;i<n;i++)  
        {  
            printf("%d",topo[i]);  
            if(i<n-1)  
            printf(" ");  
        }  
        printf("\n");         
    }  
      
    return 0;  
}  

六、欧拉回路

存在欧拉回路的情况是:最多只能两个点的入度不等于出度,而且一个点是入度比出度大1,另外一个点是出度比入度大1。前提条件是图必须是连通的。








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值