无向图,邻接链表存储,prim算法实现最小生成树,深度优先搜索,广度优先搜索。

仅实现算法过程,对输入未监测

//#include<iostream>
#include<SqQueue.h>
#include<climits>
//using namespace std;
const int MaxVectices = 100;
typedef int VerT;
typedef int DisT;
//-------------------声明定义结构体和类
struct Edge
{
    int dest;
    DisT weight;
    Edge *next;
};
struct item
{
    VerT data;
    Edge *adj;
};
struct MinSpanTree
{
    int begin, end;
    float length;
};
class AdjTWGraph
{
private:
    item Vertices[MaxVectices];
    int numV;
    int numE;
public:
    AdjTWGraph();
    ~AdjTWGraph();
    void CreatG(int n, int e);
    void PrintOut();
    void DepthFirst();
    void BroadFirst();
    void Prim(int v);
private:
    void DepthFirst(int v, int visited[]);
    void BroadFirst(int v, int visited[]);
};

//-------------------声明函数

//-------------------定义函数
AdjTWGraph::AdjTWGraph()
{
    for(int i=0; i<MaxVectices; i++)
    {
        Vertices[i].data = 0;
        Vertices[i].adj = nullptr;
    }
    numE = 0;
    numV = 0;
}

AdjTWGraph::~AdjTWGraph()
{
    for(int i=0; i<numV; i++)
    {
        Edge *p = Vertices[i].adj, *q;
        while(p!=nullptr)
        {
            q = p->next;
            delete p;
            p = q;
        }
        Vertices[i].adj = nullptr;
    }
    cout<<"\n调用析构函数";
}

void AdjTWGraph::CreatG(int n, int e)
{
    int vi,vj;
    DisT w;
    numE = e;                                       //e为边的数目,n为顶点的数目
    numV = n;
    cout<<"\n输入顶点的信息";
    for(int i=0; i<numV; i++)                       //顶点信息的输入
    {
        cout<<"\n"<<i+1<<":";
        cin>>Vertices[i].data;
    }
    for(int i=0; i<numE; i++)
    {
        cout<<"\n 请输入边的信息:顶点号vi 顶点号vj 边的权重w\n";
        cin>>vi>>vj>>w;
        if(vi<1||vj<1||vi>numV||vj>numV)
            cout<<"\n顶点号越界";
        //------------------------------第i条链表插入vi--vj
        Edge *q = new Edge;
        q->dest = vj;
        q->weight = w;
        q->next = nullptr;
        if(Vertices[vi-1].adj == nullptr)                                //插入第一条边
            Vertices[vi-1].adj = q;
        else
        {
            Edge *curr = Vertices[vi-1].adj, *pre = nullptr;
            while(curr != nullptr && (curr->dest < q->dest))              //向右搜索直到标记点到q后侧
            {
                pre = curr;
                curr = curr->next;
            }
            if(pre==nullptr)                                            //在已有链表的第一个边节点前插入
            {
                q->next = Vertices[vi-1].adj;
                Vertices[vi-1].adj = q;
            }
            else
            {
                q->next = pre->next;
                pre->next = q;
            }
        }
        //------------------------------第j条链表插入vj--vi
        Edge *p = new Edge;
        p->dest = vi;
        p->weight = w;
        p->next = nullptr;
        if(Vertices[vj-1].adj==nullptr)
            Vertices[vj-1].adj = p;
        else
        {
            Edge *curr = Vertices[vj-1].adj;
            Edge *pre = nullptr;
            while(curr!=nullptr && curr->dest<p->dest)
            {
                pre = curr;
                curr = curr->next;
            }
            if(pre==nullptr)
            {
                p->next = Vertices[vj-1].adj;
                Vertices[vj-1].adj = p;
            }
            else
            {
                p->next = pre->next;
                pre->next = p;
            }
        }
    }
}

void AdjTWGraph::PrintOut()
{
    Edge *curr, *pre;
    cout<<"\n 输出顶点信息编号,邻接点的编号和边的权重:";
    for(int i=0; i<numV; i++)
    {
        curr = Vertices[i].adj;
        cout<<"\n顶点:"<<Vertices[i].data;
        while(curr!=nullptr)
        {
            cout<<"\t邻接点 "<<Vertices[curr->dest-1].data<<"\t权重 "<<curr->weight;
            pre = curr;
            curr = curr->next;
        }
        cout<<"\n";
    }
}

void AdjTWGraph::DepthFirst(int v, int visited[])
{
    v--;
    int vj;
    Edge *p;
    cout<<Vertices[v].data<<"\t";
    visited[v] = 1;
    p = Vertices[v].adj;
    while(p!=nullptr)
    {
        vj = p->dest;
        if(visited[vj-1]==0)
            DepthFirst(vj, visited);
        p = p->next;
    }
}

void AdjTWGraph::DepthFirst()
{
    int v0;
    int visited[MaxVectices];
    for(int i=0; i<MaxVectices; i++)
        visited[i] = 0;
    cout<<"\n请输入深度遍历开始顶点";
    cin>>v0;
    cout<<"\n深度优先遍历";
    DepthFirst(v0, visited);
    cout<<"\n遍历结束";
}

void AdjTWGraph::BroadFirst(int v, int visited[])
{
    v--;
    int vj;
    Edge *p;
    SqQueue<int>Q;
    cout<<Vertices[v].data<<"\t";
    visited[v] = 1;
    Q.EnQueue(v);
    while(!Q.IsEmpty())
    {
        v = Q.DeQueue();
        p = Vertices[v].adj;
        while(p!=nullptr)
        {
            vj = p->dest;
            if(visited[vj-1]==0)
            {
                cout<<Vertices[vj-1].data<<"\t";
                visited[vj-1] = 1;
                Q.EnQueue(vj-1);
            }
            p = p->next;
        }
    }
    cout<<"\n end";
}

void AdjTWGraph::BroadFirst()
{
    int v0, visited[MaxVectices];
    for(int i=0; i<MaxVectices; i++)
        visited[i] = 0;
    cout<<"\n输入广度优先遍历起始顶点";
    cin>>v0;
    BroadFirst(v0, visited);
    cout<<"\n广度优先遍历结束";
}

//-----------------------------定义程序的函数,实现最小生成树算法
void AdjTWGraph::Prim(int v)                             //从顶点v开始的prim算法
{
    int n = numV;
    MinSpanTree e, mintree[20];
    Edge *p = Vertices[v-1].adj;
    for(int i=0; i<v-1; i++)                                //n个顶点,从v出发最多n-1条边
    {
        mintree[i].begin = v;
        mintree[i].end = Vertices[i].data;
        if(p!=nullptr && (mintree[i].end == p->dest))
        {
            mintree[i].length = p->weight;
            p = p->next;
        }
        else 
            mintree[i].length = INT_MAX;
    }
    for(int i=v-1; i<n-1; i++)                                //n个顶点,从v出发最多n-1条边
    {
        mintree[i].begin = v;
        mintree[i].end = Vertices[i+1].data;
        if(p!=nullptr && (mintree[i].end == p->dest))
        {
            mintree[i].length = p->weight;
            p = p->next;
        }
        else 
            mintree[i].length = INT_MAX;
    }

    for(int j=0; j<n-1; j++)
    {
        int min = INT_MAX;
        int jj;
        for(int m=j; m<n-1; m++)
        {
            if(mintree[m].length<min)
            {
                min = mintree[m].length;
                jj = m;
            }
        }
        e = mintree[j];
        mintree[j] = mintree[jj];
        mintree[jj] = e;
        int vv = mintree[j].end;                         //最小权值对应的顶点下标
        p = Vertices[vv-1].adj;
        while(p!=nullptr)
        {
            int k =j+1;
            for(;k<n-1;k++)
            {
                if(mintree[k].end== p->dest)
                    break;
            }
            if(p->weight < mintree[k].length && k<n-1)
            {
                mintree[k].length = p->weight;
                mintree[k].begin = vv;
            }
            p = p->next;
        }
    }
    cout<<"\nPrim算法,邻接链表存储下\n";
    for(int j=0; j<n-1; j++)
    {
        cout<<"\n第"<<j+1<<"条边起点 "<<mintree[j].begin<<" 终点 "<<mintree[j].end<<" 权重 "<<mintree[j].length;
    }
}

int main(int argc, char *argv[])
{
    AdjTWGraph G;
    int n, e, k,v;
    char ch;
    cout<<"\n\n 1.建立图的邻接链表";
    cout<<"\n 2.深度优先遍历图";
    cout<<"\n 3.广度优先遍历图";
    cout<<"\n 4.Prim算法,邻接链表存储实现最小生成树";
    cout<<"\n 5.结束程序运行";
    cout<<"\n--------------------------------";
    cout<<"\n 请输入你的选择(1,2,3,4)";
    cin>>k;
    while(k>0 && k<5)
    {
        switch(k)
        {
            case 1:
                cout<<"\n输入图的总顶点数和总边数(n,e=?)";
                cin>>n>>e;
                G.CreatG(n, e);
                G.PrintOut();
                break;
            case 2:
                G.DepthFirst();
//                G.PrintOut();
                break;
            case 3:
                G.BroadFirst();
//                G.PrintOut();
                break;
            case 4:
                cout<<"\n输入起始顶点v";
                cin>>v;
                G.Prim(v);
                break;
            default:
                break;
        }
        cout<<"\n 请输入你的选择(1,2,3,4)";
        cin>>k;
    }    
    cout<<"\n 程序结束";
    return 0;
}

模板类 SqQueue.h

#include<iostream>
using namespace std;
template<class T>class SqQueue
{
public:
    SqQueue(int sz=30);
    ~SqQueue(){delete[] elem;}
    void EnQueue(T item);
    T DeQueue();
    T GetFront();
    void MakeEmpty(){ front=rear=0;}
    bool IsEmpty(){ return front==rear;}
    bool IsFull(){ return (rear+1)&Maxsize==front;}
    int length(){ return (rear-front+Maxsize)%Maxsize;}
    void PrintOut();
private:
    int front, rear;
    T *elem;
    int Maxsize;
};

template<class T>SqQueue<T>::SqQueue(int sz)
{
    front = 0;
    rear = 0;
    Maxsize = sz;
    elem = new T[Maxsize];
    for(int i=0; i<Maxsize; i++)
        elem[i] = 0;
}

template<class T>void SqQueue<T>::EnQueue(T item)
{
    if(!IsFull())
    {
        rear = (rear+1)%Maxsize;
        elem[rear] = item;
    }
}

template<class T>T SqQueue<T>::DeQueue()
{
    if(!IsEmpty())
    {
        front = (front+1)%Maxsize;
        return elem[front];
    }
}

template<class T>T SqQueue<T>::GetFront()
{
    if(!IsEmpty())
    {
        return elem[(front+1)%Maxsize];
    }
}

template<class T>void SqQueue<T>::PrintOut()
{
    int i;
    if(IsEmpty())
        cout<<"\n队列为空";
    else
    {
        i = rear;
        while(i!=front)
        {
            cout<<elem[i]<<"\t";
            i = (i-1)%Maxsize;
        }
    }
    cout<<"\n 按任意键,继续";
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值