1. 程式人生 > >基本資料結構之樹、圖

基本資料結構之樹、圖

一、二叉樹

這裡寫圖片描述
以下采用連結串列結構來實現上圖的二叉樹:

#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;
}