基本数据结构之树、图

一、二叉树

这里写图片描述
以下采用链表结构来实现上图的二叉树:

#include <cstdlib>
#include <iostream>
using namespace std;
struct mNode
{
       int mData;
       struct mNode *left;
       struct mNode *right;
};

void PreOrder(mNode *node)
{
     if(node!=0)
     {
       printf("%d\t",node->mData);
       PreOrder(node->left);
       PreOrder(node->right);
     }
}
void InOrder(mNode *node)
{
     if(node!=0)
     {
       InOrder(node->left);
       printf("%d\t",node->mData);
       InOrder(node->right);
     }
}
void PostOrder(mNode *node)
{
     if(node!=0)
     {
       PostOrder(node->left);
       PostOrder(node->right);
       printf("%d\t",node->mData);
     }               
}
bool FindElem(mNode *node,int item)
{
     if(node==0)
       return false;
     if(node->mData==item)
       return true;
     return FindElem(node->left,item)||FindElem(node->right,item);
}

int main(int argc, char *argv[])
{
    struct mNode *node1=new struct mNode;
    node1->mData=1;
    struct mNode *node2=new struct mNode;
    node2->mData=2;
    struct mNode *node3=new struct mNode;
    node3->mData=3;
    struct mNode *node4=new struct mNode;
    node4->mData=4;
    struct mNode *node5=new struct mNode;
    node5->mData=5;
    node1->left=node2;
    node1->right=node5;
    node2->left=node3;
    node2->right=node4;
    node3->left=node3->right=node4->left=node4->right=node5->left=node5->right=0;

    PreOrder(node1);
    printf("\n");
    if(FindElem(node1,1))
      printf("true\n");
    else
      printf("false\n");
    system("PAUSE");
    return EXIT_SUCCESS;
}

二、二叉搜索树

二叉树中有一种特殊的树,名为二叉搜索树,这样的一棵树同样可以采用链表来表示,其中每个结点包含left和right指向结点的左孩子和右孩子。二叉搜索树的特点是,对于任何结点x,其左子树的关键字最大不超过x.key,其右子树的关键字不低于x.key。大部分二叉搜索树的最坏运行时间与树的高度成正比。

#include <cstdlib>
#include <iostream>

using namespace std;
struct mNode
{
       int mData;
       struct mNode *left;
       struct mNode *right;
};

void InOrder(mNode *r)
{
     if(r!=0)
     {
       InOrder(r->left);
       printf("%d\t",r->mData);
       InOrder(r->right);
     }
}
bool FindElem(mNode *r,int item)
{
     if(r==0)
       return false;
     if(r->mData==item)
       return true;
     if(r->mData>item)
       return FindElem(r->left,item);
     else
       return FindElem(r->right,item);
}
void InsertElem(mNode *&r,int item)
{
     struct mNode *pNew=new struct mNode;
     pNew->mData=item;
     pNew->left=0;
     pNew->right=0;

     struct mNode *p=r;
     struct mNode *q=0;
     while(p!=0)
     {
       q=p;
       if(p->mData>item)
         p=p->left;
       else
         p=p->right;
     }
     if(q==0)
       r=pNew;
     else
     {
       if(q->mData>item)
         q->left=pNew;
       else
         q->right=pNew;    
     }
}
bool DeleteElem(mNode *&r,int item)
{
   mNode *p=r;
   mNode *q=0;
   while(p!=0)
   {
     if(p->mData==item)
       break;
     q=p;

     if(p->mData>item)
       p=p->left;
     else
       p=p->right;
   }
   if(p==0)
     return false;
   if(p->left==0&&p->right==0)
   {
     if(q==0)
       r=0;
     else if(q->mData>p->mData)
       q->left=0;
     else
       q->right=0;
     delete p;
   }
   else if(p->left!=0&&p->right==0)
   {
     if(q==0)
       r=r->left;
     else if(q->mData>p->mData)
       q->left=p->left;
     else
       q->right=p->left;
     delete p;
   }
   else if(p->left==0&&p->right!=0)
   {
     if(q==0)
       r=r->right;
     else if(q->mData>p->mData)
       q->left=p->right;
     else
       q->right=p->right;      
     delete p;
   }
   else
   {
     mNode *temp=p->left;
     while(temp->right!=0)
     {
      temp=temp->right; 
     }
     temp->right=p->right;
     if(q==0)
       r=r->left;
     else if(q->mData>p->mData)
       q->left=p->left;
     else
       q->right=p->left;
     delete p;
   }
   return true;
}

int main(int argc, char *argv[])
{
    struct mNode *root=new struct mNode;
    root->mData=23;
    struct mNode *node1=new struct mNode;
    node1->mData=12;
    struct mNode *node2=new struct mNode;
    node2->mData=15;
    struct mNode *node3=new struct mNode;
    node3->mData=28;
    struct mNode *node4=new struct mNode;
    node4->mData=30;
    struct mNode *node5=new struct mNode;
    node5->mData=35;
    struct mNode *node6=new struct mNode;
    node6->mData=40;

    root->left=node2;
    node2->left=node1; node2->right=0;
    node1->left=0; node1->right=0;
    root->right=node5;
    node5->left=node3; node5->right=node6;
    node3->left=0; node3->right=node4;
    node4->left=0; node4->right=0;
    node6->left=0; node6->right=0;

    InOrder(root);
    InsertElem(root,24);
    InOrder(root);
    printf("\n");
    DeleteElem(root,28);
    InOrder(root);
    system("PAUSE");
    return EXIT_SUCCESS;
}

三、图

对于图G=(V,E),可以用两种方法来表示,一种将图作为邻接链表的组合,另一种将图作为邻接矩阵来看待。
这里写图片描述

我们先用邻接矩阵来实现这张图:
struct Vertex
{
     int mData;
     bool mVisit;
};
struct Edge
{
     int mV1;
     int mV2;
};
struct Graph
{
     Vertex mVertexSet[100];
     int mVertexNum;
     bool mMatrix[100][100];
};

void ResetVisit(Graph &G)
{
     for(int i=0;i<G.mVertexNum;i++)
     {
         G.mVertexSet[i].mVisit=false;
     }
}
void CreateGraph(Graph &G,Vertex V[],int Vnum,Edge E[],int Enum)
{
     G.mVertexNum=Vnum;
     for(int i=0;i<Vnum;i++)
     {
         G.mVertexSet[i]=V[i];
     }
     for(int i=0;i<Vnum;i++)
     {
         for(int j=0;j<Vnum;j++)
         {
             G.mMatrix[i][j]=false;
         }
     }
     for(int i=0;i<Enum;i++)
     {
         G.mMatrix[E[i].mV1][E[i].mV2]=true;
     }
}

int FirstAdjVertex(Graph &G,int v)
{
    for(int i=0;i<G.mVertexNum;i++)
    {
         if(G.mMatrix[v][i])
             return i;
    }
    return -1;
}
int NextAdjVertex(Graph &G,int v,int w)
{
    for(int i=w+1;i<G.mVertexNum;i++)
    {
         if(G.mMatrix[v][i])
             return i;
    }
    return -1;
}

因为需要进行BFS操作,我们又定义了一个队列:

struct MyQueue
{
       int mSet[100];
       int mHead;
       int mTail;
       int mLen;
};

void InitQueue(MyQueue &Q)
{
      Q.mHead=0;
      Q.mTail=0;
      Q.mLen=0;
}
void EnQueue(MyQueue &Q,int item)
{
      Q.mSet[Q.mTail]=item;
      Q.mTail=(Q.mTail+1)%100;
      Q.mLen++;
}
int DeQueue(MyQueue &Q)
{
     int r=Q.mSet[Q.mHead];
     Q.mHead=(Q.mHead+1)%100;
     Q.mLen--;
     return r;
}
bool IsEmptyQueue(MyQueue Q)
{
     if(Q.mLen==0)
         return true;
     return false;
}

主函数如下:

#include <cstdlib>
#include <iostream>
#include "graph1.h"
#include "queue3.h"

using namespace std;

void DFS(Graph &G,int v)
{
     printf("%d\t",G.mVertexSet[v].mData);
     G.mVertexSet[v].mVisit=true;
     for(int w=FirstAdjVertex(G,v);w!=-1;w=NextAdjVertex(G,v,w))
     {
         if(G.mVertexSet[w].mVisit==false)
             DFS(G,w);
     }
}
void BFS(Graph &G,int v)
{
     MyQueue Q;
     InitQueue(Q);
     EnQueue(Q,v);
     while(!IsEmptyQueue(Q))
     {
         int w=DeQueue(Q);
         if(G.mVertexSet[w].mVisit==false)
         {
             printf("%d\t",G.mVertexSet[w].mData);
             G.mVertexSet[w].mVisit=true;
         }
         for(int u=FirstAdjVertex(G,w);u!=-1;u=NextAdjVertex(G,w,u))
         {
             if(G.mVertexSet[u].mVisit==false)
                 EnQueue(Q,u);
         }
     }
}
int main(int argc, char *argv[])
{
    Vertex VSet[6];
    VSet[0].mData=0;VSet[1].mData=1;VSet[2].mData=2;
    VSet[3].mData=3;VSet[4].mData=4;VSet[5].mData=5;

    Edge ESet[16];
    ESet[0].mV1=0;ESet[0].mV2=1; ESet[1].mV1=1;ESet[1].mV2=0; 
    ESet[2].mV1=0;ESet[2].mV2=2; ESet[3].mV1=2;ESet[3].mV2=0;
    ESet[4].mV1=0;ESet[4].mV2=3; ESet[5].mV1=3;ESet[5].mV2=0;
    ESet[6].mV1=0;ESet[6].mV2=4; ESet[7].mV1=4;ESet[7].mV2=0;

    ESet[8].mV1=1;ESet[8].mV2=4; ESet[9].mV1=4;ESet[9].mV2=1; 
    ESet[10].mV1=2;ESet[10].mV2=4; ESet[11].mV1=4;ESet[11].mV2=2;
    ESet[12].mV1=3;ESet[12].mV2=5; ESet[13].mV1=5;ESet[13].mV2=3; 
    ESet[14].mV1=4;ESet[14].mV2=5; ESet[15].mV1=5;ESet[15].mV2=4;
    Graph G;
    CreateGraph(G,VSet,6,ESet,16);
    ResetVisit(G);
    DFS(G,0);
    printf("\n");
    ResetVisit(G);
    BFS(G,0);
    system("PAUSE");
    return EXIT_SUCCESS;
}
我们再用邻接表来实现上图:
#include <cstdlib>
#include <iostream>
#include "queue3.h"

using namespace std;
struct Edge
{
     int index;
     Edge *nextAdjEdge;
};
struct Vertex
{
     int mData;
     bool mVisit;
     Edge *firstAdjEdge;             
};
struct Graph
{
     Vertex adjList[100];
     int vertexNum;
     int edgeNum;

};
void resetVisit(Graph &G)
{
     for(int i=0;i<G.vertexNum;i++)
         G.adjList[i].mVisit=false;
}
void createGraph(Graph &G,int vertexNum,Vertex v[],int edgeNum,Edge e[])
{
     G.vertexNum=vertexNum;
     G.edgeNum=edgeNum;
     for(int i=0;i<vertexNum;i++)
     {
         G.adjList[i]=v[i];
     }
}
int FirstAdjVertex(Graph G,int vertexNum)
{
     if(G.adjList[vertexNum].firstAdjEdge!=NULL)
         return G.adjList[vertexNum].firstAdjEdge->index;
     return -1;
}
int NextAdjVertex(Graph G,int v,int w)
{
    Edge *edge=G.adjList[v].firstAdjEdge;
    while(edge->index!=w)
    {
        edge=edge->nextAdjEdge;
    }
    edge=edge->nextAdjEdge;
    if(edge==NULL)
        return -1;
    return edge->index;
}
void DFS(Graph &G,int v)
{
     printf("%d\t",G.adjList[v].mData);
     G.adjList[v].mVisit=true;
     for(int w=FirstAdjVertex(G,v);w!=-1;w=NextAdjVertex(G,v,w))
     {
         if(G.adjList[w].mVisit==false)
             DFS(G,w);
     }
}
void BFS(Graph &G,int v)
{
     MyQueue Q;
     InitQueue(Q);
     EnQueue(Q,v);
     while(!IsEmptyQueue(Q))
     {              
         int w=DeQueue(Q);
         if(G.adjList[w].mVisit==false)
         {                          
             printf("%d\t",G.adjList[w].mData);
             G.adjList[w].mVisit=true;
         }
         for(int u=FirstAdjVertex(G,w);u!=-1;u=NextAdjVertex(G,w,u))
         {
             if(G.adjList[u].mVisit==false)
                 EnQueue(Q,u);
         }
     }                   
}

int main(int argc, char *argv[])
{
    Graph G;
    Edge E[16];
    E[0].index=1;E[0].nextAdjEdge=&E[1];E[1].index=2;E[1].nextAdjEdge=&E[2];
    E[2].index=3;E[2].nextAdjEdge=&E[3];E[3].index=4;E[3].nextAdjEdge=NULL;
    E[4].index=0;E[4].nextAdjEdge=&E[5];E[5].index=4;E[5].nextAdjEdge=NULL;
    E[6].index=0;E[6].nextAdjEdge=&E[7];E[7].index=4;E[7].nextAdjEdge=NULL;
    E[8].index=0;E[8].nextAdjEdge=&E[9];E[9].index=5;E[9].nextAdjEdge=NULL;
    E[10].index=0;E[10].nextAdjEdge=&E[11];E[11].index=1;E[11].nextAdjEdge=&E[12];
    E[12].index=2;E[12].nextAdjEdge=&E[13];E[13].index=5;E[13].nextAdjEdge=NULL;
    E[14].index=3;E[14].nextAdjEdge=&E[15];E[15].index=4;E[15].nextAdjEdge=NULL;

    Vertex V[6];
    V[0].mData=0; V[0].firstAdjEdge=&E[0];
    V[1].mData=1; V[1].firstAdjEdge=&E[4];
    V[2].mData=2; V[2].firstAdjEdge=&E[6];
    V[3].mData=3; V[3].firstAdjEdge=&E[8];
    V[4].mData=4; V[4].firstAdjEdge=&E[10];
    V[5].mData=5; V[5].firstAdjEdge=&E[14];
    createGraph(G,6,V,8,E);
    resetVisit(G);
    DFS(G,0);
    printf("\n");
    resetVisit(G);
    BFS(G,0);
    system("PAUSE");
    return EXIT_SUCCESS;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值