数据结构课程作业

给出如下算法时间复杂度的详细求解步骤

for(i=1;i<=n;i=2*i)
    cout<<"i="<<i;

解:
i=2*i执行x次,则x呈2^n增长,当i>n,i>2*i不再执行。
所以2^x-1<=n且2^x>n
(log_2 ^n)

给出冒泡算法时间复杂度的详细求解步骤,并求最好和最坏的情况下的时间复杂度
解:
最好的情况,序列本身就是正序,此时只需要比较第一个for里面的语句,T(n)=O(n)
最坏的情况,序列是倒序,把最小的数移到最大数的前面需要n-1次,第二小的数需要n-2次,总的次数为n-1+n-2+…+1=n(n-1)/2,所以T(n)=O(n^2)

题目一(个人完成,共30分): 带环、相交链表问题
要求

  • 1.构造链表后,将元素值为m和n(从键盘输入,如有多个相同元素值,仅考虑首个出现的元素)的节点建立连接。
  • 2.利用课程ppt中关于判断链表是否有环的方法,判断链表是否有环路,并需给出环路出现的位置,即m,n节点的序号,请使用环路判断函数。
  • 3.将环路链接取消,恢复成单链表。
  • 4.编写函数,判断两个链表是否相交,函数输入为双头相交链表的两个头指针并输出相交的位置。

代码如下

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

# define Max 10
int compare;

template <typename T>
struct LinkList
{
    T data;
    LinkList<T> *next;
};

template <typename T>
class LinkListClass
{
private:
    LinkList<T> *head;
public:
    LinkListClass<T>(){
        head= new LinkList<T>();
        head->next=NULL;
    }
    ~LinkListClass<T>();
    void LLInitiate(T a[],int n);
    void LLInput();
    LinkList<T> *MakeCross(int m,int n);
    LinkList<T> *Gethead() { return head;}
    int CheckCycle(LinkList<T> *Head,int &m,int &n);
    void RecoveryCross(LinkList<T> *Head,int m,int n);
    int  CheckCross(LinkList<T> *Head,int &count);
};//链表类的声明


template <typename T>
LinkListClass<T>::~LinkListClass<T>()
{
    LinkList<T> *p,*q;
        p=head;
        q=head->next;
        while(q!=NULL)
        {
                delete p;
                p=q;
                q=q->next;
        }
}

template <typename T>
void LinkListClass<T>::LLInitiate(T a[],int n)
{
    LinkList<T> *s,*r;
    int i;
    r=head;
    for(i=0;i<n;i++)
    {
        s=new LinkList<T>();
        s->data=a[i];
        r->next=s;
        r=s;
    }
    r->next=NULL;
}

template <typename T>
void LinkListClass<T>::LLInput()
{
    cout<<"The linklist iput like bellow:"<<endl;
    LinkList<T> *p;
    p=head->next;
    while(p!=NULL)
    {cout<<p->data<<"  ";p=p->next;}
    cout<<endl;
}


template <typename T>
LinkList<T> *LinkListClass<T>::MakeCross(int m,int n)
{
    LinkList<T> *Ferry,*Ferry_1,*head_1,*head_2;//
    LinkList<T> *Head=new LinkList<T>();
    head_2=head;
    head_1=head;
    if(m<0||n<0) {cout<<"The m or n is wrong"<<endl;exit(0);}
    //int j=0,i=0;
    while(head_1->data!=m)//找到m
        head_1=head_1->next;
    while(head_2->data!=n)//找到n
        head_2=head_2->next;
    if(m<n)
    {
        if(head_2->next!=NULL)
            Ferry=head_2->next;//摆渡指向n的下一个节点
        if(head_2->next==NULL)
            {   //表示n是链表的最后一个元素
                head_2->next=head_1;//n的next指向m
                return NULL;
            }
        compare=head_2->data;//记录新链表的最后一个值
        head_2->next=head_1;//n指向m以形成环
        Ferry_1=Ferry;//摆渡是n的next
        while(Ferry_1->next!=NULL)
            Ferry_1=Ferry_1->next;//将摆渡1号移到链表的最后一位
        Ferry_1->next=head_1;//让摆渡1号指向m
        Head->next=Ferry;//Head指向摆渡即n的next
        return Head;//返回头部
    }
    else
    {
        if(head_1->next!=NULL)
            Ferry=head_1->next;
        if(head_1->next==NULL)
            {
                head_1->next=head_2;
                return NULL;
            }
        head_1->next=head_2;
        compare=head_1->data;
        Ferry_1=Ferry;
        while(Ferry_1->next!=NULL)
            Ferry_1=Ferry_1->next;
        Ferry_1->next=head_2;
        Head->next=Ferry;
        return Head;
    }
}


template <typename T>
int LinkListClass<T>::CheckCycle(LinkList<T> *Head,int &m,int &n)
{
    LinkList<T> *fast=head,*slow=head,*head_1=head,*head_2=head;
    int i=0,j=0;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast)
            {
                cout<<"Cycle exist"<<endl;
                break;
            }
    }
    if(fast==NULL||fast->next==NULL)
        return 0;
    fast=head;
    cout<<"Match processing"<<endl;//显示查找环的匹配过程
    while(fast!=slow)
    {
        fast=fast->next;
        cout<<fast->data<<endl;
        slow=slow->next;
        cout<<slow->data<<endl;
    }
    cout<<endl<<"The enter is "<<slow->data<<endl;//找到环的入口
    while(head_1!=fast)
    {
        head_1=head_1->next;
        i++;
    }//找到环的出口
    m=i;
    head_2=head_1;
    cout<<"The cycle has fectors like beloow:"<<endl;
    while(head_2->next!=fast)
    {
        cout<<head_2->data<<" ";
        head_2=head_2->next;
        j++;
    }//输出环的内容
    cout<<compare<<endl;
    n=j+i;
    return 1;
}


template <typename T>
int LinkListClass<T>::CheckCross(LinkList<T> *Head,int &count)
{
    LinkList<T> *fast=head,*slow=Head,*head_1=head;
    int j,i=0;
    bool flag=false;
    while(fast&&fast->next)
    {   //判断相交之前判断是否有环,有相交点即是环的入口
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast)
            {
                cout<<"The link has a cycle"<<endl;
                flag=true;
                break;
            }
    }
    if(flag==true)
    {   //存在环找到入口即可
        if(fast==NULL||fast->next==NULL)
            return 0;
        fast=head;
        while(fast!=slow)
        {
            fast=fast->next;
            slow=slow->next;
        }
        while(head_1!=fast)
        {
            head_1=head_1->next;
            i++;
        }
        count=i;
    }
    else//没有环,通过算法找到相交点
    {
        int abs;
        fast=head;
        slow=Head;
        for(i=1;fast->next!=NULL;i++)
            fast=fast->next;//fast指向head的最后一个元素
        for(j=1;slow->next!=NULL;j++)
            slow=slow->next;//sloa指向Head的最后一个元素
        if(slow==fast)
        {   //如果Head和head的最后元素相同,即相交
            cout<<"Links has a cross."<<endl;
            if(i>j)
            {   //head比Head长
                fast=head;
                slow=Head;//两指针从头开始
                abs=i-j;//head比Head长多少
                for(int m=0;m<abs;m++)
                    fast=fast->next;//让长的先走完多的几步,这样余下的节点数一样长
                while(fast!=slow)
                {   //找到fast==slow的位置即是交叉点
                    fast=fast->next;
                    slow=slow->next;
                }
                count=slow->data;
            }
            else
            {
                fast=head;
                slow=Head;
                abs=j-i;
                for(int m=0;m<abs;m++)
                    slow=slow->next;
                while(fast!=slow)
                {
                    fast=fast->next;
                    slow=slow->next;
                }
                count=slow->data;
            }

        }
    }
    return 1;
}


template <typename T>
void LinkListClass<T>::RecoveryCross(LinkList<T> *Head,int m,int n)
{//在相交的情况下恢复
    LinkList<T> *head_1=head,*Head_1=Head;
    //int j=0,i=0;
    while(head_1->data!=n)
    {   //找到相交链表的最后一个值,让head_1指向链表的末尾
        head_1=head_1->next;
    }
    head_1->next=NULL;
    /*head_1->next=Head->next->next;
    while(Head_1->next->data!=m)
    {   //这步是为了去第二条链表的头部,将第二条链表指向m的上一个节点指向NULL
        Head_1=Head_1->next;
    }
    Head_1->next=NULL;*/
    //delete Head;
}


void Menu()
{
    cout<<"***************************************"<<endl;
    cout<<"*  MakeCycle---------------------1    *"<<endl;
    cout<<"*  FindCycle---------------------2    *"<<endl;
    cout<<"*  Recovery----------------------3    *"<<endl;
    cout<<"*  FindCross ---------------------4    *"<<endl;
    cout<<"*  Exit--------------------------0    *"<<endl;
    cout<<"*        input number to exe          *"<<endl;
    cout<<"***************************************"<<endl;
}



int main()
{
    LinkListClass<int>  mylist;
    LinkList<int> *Head,*Head_2,*Head_3;
    int a[Max];
    int m,n,count=0,i=0;
    //cout<<"Please input your number"<<endl;
    for(i=0;i<10;i++)
    {
        //cin>>a[i];
        a[i]=i+1;
    }
    mylist.LLInitiate(a,Max);
    mylist.LLInput();
    Menu();
    for (;;)
    {
        cin >> i;
        cout << endl;
        switch (i)
        {
        case 1:
                cout<<"Please input m and n"<<endl;
                cin>>m>>n;
                Head=mylist.MakeCross(m,n);
                Head_3=mylist.Gethead()->next;
                cout<<"The first link likes bellow"<<endl;
                for(;Head_3->data!=compare;Head_3=Head_3->next)
                    cout<<Head_3->data<<" ";
                cout<<compare<<endl;
                cout<<"The second link likes bellow"<<endl;
                Head_2=Head->next;
                for(;Head_2->data!=compare;Head_2=Head_2->next)
                    cout<<Head_2->data<<" ";
                cout<<compare<<endl;
                break;
        case 2:
                mylist.CheckCycle(Head,m,n);
                cout<<"Cycle begin with "<<m<<" end with "<<n<<endl;
                break;
        case 3:
               mylist.RecoveryCross(Head,m,n);
                mylist.LLInput();
                break;
        case 4:

                 if(mylist.CheckCross(Head,count))
                    cout<<"Cross exist and its number is "<<count<<endl;
                else
                    cout<<"no cross"<<endl;
                break;
        default: {exit(0); break; }
        }
        cout << endl << endl;
        Menu();
    }
    return 0;
}

题目二(个人完成,共40分):交通咨询系统设计
设计目的:
熟练掌握迪杰斯特拉算法和费洛伊德算法,能够利用它们解决最短路径问题。
掌握图的深度,广度遍历算法。
掌握快速排序算法。
设计内容:
设计一个交通咨询系统,通过读取全国城市距离图,能够让用户查询从任一个城市定点到另一个城市定点之间的最短路径以及所有不重复的可行路径,并利用快速排序对所有路径方案依据总长度进行排序输出(输出到文件),每一条结果均需包含路径信息及总长度。
代码如下

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <memory.h>
#include <algorithm>
using namespace std;
//头文件声明

# define MaxWeight 10000    //最大距离,表示不可直达

class Graph
{
    private:
            int vexnum=34;  //城市数
            int count_way=0,way_weight=0;   //此条路的城市数和此路的权值
            string Vex[35]={"北京","上海","天津","重庆","哈尔滨","长春","沈阳","呼和浩特","石家庄","太原",
                            "济南","郑州","西安","兰州","银川","西宁","乌鲁木齐","合肥","南京","杭州","长沙",
                            "南昌","武汉","成都","贵阳","福州","台北","广州","海口","南宁","昆明","拉萨","香港","澳门"};
            int city_reach[34][34]; //可达矩阵
            int city_weight[34][34];    //权值矩阵
            int city_three[34][34]={-1};    //将可达矩阵和权值矩阵组成新的矩阵
            int visited[35]={0};    //访问标记数组,访问为1,否则为0
            vector<int> path_WayMark;  //深度搜索时访问标记数组
            vector<vector<int> > all_way; //深度搜索时保存所有的路径
            vector<int> way_number; //保存同起点、同终点的不同路径的权值
            vector<int> weight_array;   //同上,但这个是快速排序时用到
    public:
            Graph();
            ~Graph(){;}
            void DFS(int Ve_one,int Ve_two);    //深搜
            void check(string str_one,string str_two,int &Ve_one,int &Ve_two);  //判断输入城市的正确性并返回错误信息或城市的序号
            int   GetFirstVex(Graph *G,int v);  //取城市的第一个邻接点
            int   GetNextVex(Graph *G,int v,int w); //取城市的下一个邻接点
            int   GetWeight(int Ve_one,int Ve_two) {    return city_three[Ve_one][Ve_two];  }   //获取城市的权值
            void Dijkstra(Graph *G, int Ve_one, int Ve_two,int distance[], int path[]); //迪杰斯特拉查找最短路径
            void SearchPath_Dijkstra(int path[],int distance[],int Ve_one,int  Ve_two); //输出迪杰斯特拉查找的路径
            void Floyd(int city_three_copy[34][34],int path_two[34][34]);   //弗洛德查找最短路径
            void SearchPath_Floyd(int Ve_one,int  Ve_two,int city_three_copy[][34],int path_two[][34]); //输出弗洛德拉查找的路径
            void Quick_Sort(int low, int high); //快速排序
            int   get_SizeOfWeight(){   return way_number.size();   }   //返回深搜中的路径总数
            void write_file();  //结果写入到文件
            void show() //输出深搜中的所有路径的权值
            {
                for(unsigned i=0;i<weight_array.size();i++)
                {
                    cout<<weight_array[i]<<"    ";
                    if(i%20==0)
                        cout<<endl;
                }
            }
};

Graph::Graph(){
    string value_reach,value_weight;
    ifstream file_in_one("/home/lking/Desktop/Test_two/Data_reach.txt");    //取可达矩阵
    ifstream file_in_two("/home/lking/Desktop/Test_two/Data_weight.txt");   //取权值矩阵
    if(!file_in_one.is_open())
        cout<<"Failed to open Date_reach.txt!"<<endl;
    if(!file_in_two.is_open())
        cout<<"Failed to open Date_weight.txt!"<<endl;
    int i=0,j;
    while(file_in_one.good())
    {   //读可达矩阵
        getline(file_in_one,value_reach);
        stringstream ss_one(value_reach);
        j=0;
        while(getline(ss_one,value_reach,'\t'))
        {
            city_reach[i][j]=atoi(value_reach.c_str());
            j++;
        }
        ss_one.clear();
        ss_one.str();
        i++;
    }
    file_in_one.close();
    i=0;
    while(file_in_two.good())
    {   //读权值矩阵
        getline(file_in_two,value_weight);
        stringstream ss_two(value_weight);
        j=0;
        while(getline(ss_two,value_weight,'\t'))
        {
            city_weight[i][j]=atoi(value_weight.c_str());
            j++;
        }
        ss_two.clear();
        ss_two.str();
        i++;
    }
    file_in_two.close();
    for(i=0;i<34;i++)
    {   //将两个矩阵组合到city_three矩阵中,可达即为相应的权值,否则为MaxWeight
        for(j=0;j<34;j++)
        {
            if(city_reach[i][j]==1)
            {
                if(city_weight!=0)
                    city_three[i][j]=city_weight[i][j];//reach and weight
            }
            if(city_reach[i][j]==0)
                city_three[i][j]=MaxWeight;
        }
    }
    for(i=0;i<34;i++)
    {   //上面所得city_three为下三角矩阵,这里转化为全矩阵(对称矩阵)
        for(j=0;j<34;j++)
        {
            if(city_three[i][j]!=MaxWeight)
                city_three[i][j]=city_three[j][i];
            if(i==j)
                city_three[i][j]=MaxWeight;
        }
    }
}
/*
int Graph::GetFirstVex(Graph *G,int v)
{
    int col;
    if(v<0||v>(G->vexnum-1))
    {   //判断序号的合法性
        cout<<"参数越界"<<endl;
        exit(1);
    }
    for(col=0;col<vexnum;col++) //序号合法即返回他的一个可达序号
        if(city_three[v][col]>1&&city_three[v][col]<MaxWeight)
            return col;
    return -1;  //没有可达返回-1
}*/
/*
int Graph::GetNextVex(Graph *G,int v,int w)
{   //获取v的下一个顶点
    int i;
    if(v<0||v>(G->vexnum-1)||w<0||w>(vexnum-1))
        return -1;
    for(i=w+1;i<vexnum;i++) //从访问过的w号城市开始寻找v的下一个可达序号
        if(city_three[v][i]>0||city_three[v][i]<MaxWeight)
            return i;
    return -1;
}*/

/*没有进行扩容,简单利用push_back进行二维vector初始化
//int visited[34]={0};    //深度搜索的访问标记数组,访问为1,否则为0
int note,note_one=0,note_three=0;   //标记位
void Graph::DFS(int Ve_one,int Ve_two)
{
    if(path_WayMark.size()>=10)    //返回出口,当标记城市>=10时不返回
        return;
    path_WayMark.push_back(Ve_one);    //将当前访问城市标记
    if(Ve_one==Ve_two)
    {   //找到一条路径
        ++count_way;    //统计路径总数
        //all_way_row.push_back(count_way-1);
        //all_way.push_back(count_way-1);
        int j=0,k=0,i=count_way-1;  //i的初始化为count_way-1是为了确保每次只增加一条路径
        for(auto it=path_WayMark.begin();it!=path_WayMark.end();++it)
        {
            k++;//将路径存入数组all_path时,为保持数组的列下标一致
            if(city_three[*(it-1)][*it]<10000)  //将路径上不同城市的权值进行加和
                way_weight+=city_three[*(it-1)][*it];
            //for(;j<10;j++)
            //{
                all_way_row.push_back(*it);
                //all_way[i][j]=*it;
            //}
            //all_way_row.push_back(way_weight);
            //all_way.push_back(all_way_row);
            //all_way[i][10]=way_weight;  //all_way每行的最后一个元素为此条路径的权值
            //all_way_row.clear();
            //j=k;//下标更新,否则j为9,下次不能进入all_way的二重循环
            cout<<Vex[*it];
        }
        all_way_row.push_back(way_weight);
        all_way.push_back(all_way_row);
                    //all_way[i][10]=way_weight;  //all_way每行的最后一个元素为此条路径的权值
        all_way_row.clear();
                    //j=k;//下标更新,否则j为9,下次不能进入all_way的二重循环
                    //cout<<Vex[*it];
        cout<<endl;
        cout<<note<<"   "<<way_weight;
        //for(int i=count_way-1;i<count_way;i++)
    //  {   //记录路径权值,一个用作排序,一个保持权值和路径的对应
            way_number.push_back(way_weight);
            weight_array.push_back(way_weight);
    //  }
        way_weight=0;   //下一条路径的权值从0开始
    }
    else
    {   //没有找到路径
        for(int i=0;i<vexnum;i++)
        {   //从0号城市开始查找
            vector<int>::iterator iter=find(path_WayMark.begin(),path_WayMark.end(),i);
            if(city_three[Ve_one][i]<MaxWeight && Ve_one!=i && iter==path_WayMark.end())
            {   //若当前城市和我的Ve_one可达,且不是我的Ve_one,也不再我当前的路径上则纳入路径继续深度搜索
                DFS(i,Ve_two);  //将上一个城市标记移除后返回这里继续上一个转折城市的下一个城市搜索
            }
        }
    }
    path_WayMark.pop_back();    //以当前城市为转接点的路径查找后要将其标记移除,因为他可能是下一个转折点构成路径的城市
}*/
//int visited[34]={0};    //深度搜索的访问标记数组,访问为1,否则为0
int note,note_one=0,note_three=0;   //标记位
void Graph::DFS(int Ve_one,int Ve_two)
{
    if(path_WayMark.size()>=10)    //返回出口,当标记城市>=10时不返回
        return;
    path_WayMark.push_back(Ve_one);    //将当前访问城市标记
    if(Ve_one==Ve_two)
    {   //找到一条路径
        ++count_way;    //统计路径总数
        all_way.resize(count_way);  //将all_way矩阵的行进行扩容
        for(note=count_way-1;note<count_way;note++)     //将all_way矩阵的列进行扩容
            all_way[note].resize(11);
        int j=0,k=0,i=count_way-1;  //i的初始化为count_way-1是为了确保每次只增加一条路径
        for(auto it=path_WayMark.begin();it!=path_WayMark.end();++it)
        {
            k++;//将路径存入数组all_path时,为保持数组的列下标一致
            if(city_three[*(it-1)][*it]<10000)  //将路径上不同城市的权值进行加和
                way_weight+=city_three[*(it-1)][*it];
            for(;j<10;j++)
            {
                all_way[i][j]=*it;
            }
            all_way[i][10]=way_weight;  //all_way每行的最后一个元素为此条路径的权值
            j=k;//下标更新,否则j为9,下次不能进入all_way的二重循环
            //cout<<Vex[*it];
        }
        //cout<<endl;
//cout<<note<<" "<<way_weight;
        for(int i=count_way-1;i<count_way;i++)
        {   //记录路径权值,一个用作排序,一个保持权值和路径的对应
            way_number.push_back(all_way[i][10]);
            weight_array.push_back(all_way[i][10]);
        }
        way_weight=0;   //下一条路径的权值从0开始
    }
    else
    {   //没有找到路径
        for(int i=0;i<vexnum;i++)
        {   //从0号城市开始查找
            vector<int>::iterator iter=find(path_WayMark.begin(),path_WayMark.end(),i);
            if(city_three[Ve_one][i]<MaxWeight && Ve_one!=i && iter==path_WayMark.end())
            {   //若当前城市和我的Ve_one可达,且不是我的Ve_one,也不再我当前的路径上则纳入路径继续深度搜索
                DFS(i,Ve_two);  //将上一个城市标记移除后返回这里继续上一个转折城市的下一个城市搜索
            }
        }
    }
    path_WayMark.pop_back();    //以当前城市为转接点的路径查找后要将其标记移除,因为他可能是下一个转折点构成路径的城市
}

//核对输入城市名,返回标号
void Graph::check(string str_one,string str_two,int &Ve_one,int &Ve_two)
{
    bool flag_one=false,flag_two=false; //标志位
    for(int i=0;i<34;i++)
        {
            if(flag_one==false&&str_one==Vex[i])
            {
                flag_one=true;
                Ve_one=i;
            }
            else if(flag_two==false&&str_two==Vex[i])
            {
                flag_two=true;
                Ve_two=i;
            }
            if(flag_one&&flag_two)
                break;
        }
    if(!flag_one&&!flag_two)
    {
        cout<<"没有您输入的城市"<<endl;
        exit(0);
    }
}

//迪杰斯特拉算法
void Graph::Dijkstra(Graph *G,int Ve_one,int Ve_two,int distance[],int path[])
{
    int minDis,i,j,u;   //不同的标记
    int *vex_flag=new int[vexnum];  //城市标记,访问为1,否则为0
    for(i=0;i<vexnum;i++)
    {   //第一次循环实现初始化,更新distance数组和标记数组vex_flag
        distance[i]=city_three[Ve_one][i];//dstance存入Ve_one和其他城市的权值
        vex_flag[i]=0;
        if(i!=Ve_one&&distance[i]<MaxWeight)
            path[i]=Ve_one; //当前城市和我的起始城市直接可达,则将当前城市纳入最短路径
        else
            path[i]=-1; //不直接可达
    }
    vex_flag[Ve_one]=1;//标记定点Ve_one加入从集合T未加入添加到vex_flag集合这种中,表示已添加
    for(i=1;i<vexnum;i++)
    {   //在为找到最短路径的城市中选取具有最短距离的城市u
        minDis=MaxWeight;
        for(j=0;j<vexnum;j++)
            if(vex_flag[j]==0&&distance[j]<minDis)
                {   //不在vex_flag中且可达
                    u=j;
                    minDis=distance[j];//对最小距离的更新
                }
        if(minDis==MaxWeight) return;//不存在路径时结束,对于非连通图而言相当于遍历了一次,找不到就是没有路径了
        vex_flag[u]=1;//找到的定点添加标记
        for(j=0;j<vexnum;j++) //添加u之后,之前的标记城市最小距离的更新
            if(vex_flag[j]==0&&G->GetWeight(u,j)<MaxWeight&&distance[u]+G->GetWeight(u,j)<distance[j])
            {   //顶点Ve_one经过u到其他顶点的最小距离的更新
                distance[j]=distance[u]+G->GetWeight(u,j);
                path[j]=u;
            }
    }
    delete[] vex_flag;
}

//输出迪杰斯特拉找到的路径
void Graph::SearchPath_Dijkstra(int path[],int distance[],int Ve_one,int Ve_two)
{
    int path_note[34];  //将路径上的城市存入path_note
    int i,top=1;
    path_note[top++]=Ve_two;
    int temp=path[Ve_two];
    while(temp!=-1)
    {   //将已保存好路径的path数组的城市放入path_note
        path_note[top++]=temp;
        temp=path[temp];
    }
    path_note[top]=Ve_one;
    for(i=top-1;i>1;--i)
            cout<<Vex[path_note[i]]<<"======>>";
    cout<<Vex[Ve_two];
    cout<<" "<<"相距"<<distance[Ve_two]<<endl;
}

//弗洛德算法
void Graph::Floyd(int city_three_copy[34][34],int path_two[34][34])
{
    int i,j,k;  //标记
    for(i=0;i<vexnum;i++)
        for(j=0;j<vexnum;j++)
            city_three_copy[i][j]=city_three[i][j]; //复制一份city_three
    for(k=0;k<vexnum;k++)
    {   //k是中间城市
        for(i=0;i<vexnum;i++)
            for(j=0;j<vexnum;j++)
                if(city_three_copy[i][j]>city_three_copy[i][k]+city_three_copy[k][j])
                {   //以中间城市为转折,若他到i的距离加上到j距离<ij的直接距离,则更新
                    //并且将path_two矩阵坐标为ij的值存为k,表示这是他们的转折点
                    city_three_copy[i][j]=city_three_copy[i][k]+city_three_copy[k][j];
                    path_two[i][j]=k;
                }
    }
}

//输出Floyd路径
void  Graph::SearchPath_Floyd(int Ve_one,int Ve_two,int city_three_copy[][34],int path_Floyd[][34])
{
    if(path_Floyd[Ve_one][Ve_two]==-1)
    {   //Ve_one和Ve_two城市没有转折城市
        cout<<Vex[Ve_one]<<"=======>>"<<Vex[Ve_two]<<endl;
        return; //递归出口
    }
    else
    {   //存在转折城市
        int i=path_Floyd[Ve_one][Ve_two]; //取出转折城市,继续递归输出
        SearchPath_Floyd(Ve_one,i,city_three_copy,path_Floyd);
        SearchPath_Floyd(i,Ve_two,city_three_copy,path_Floyd);
    }
}

//快速排序
void Graph::Quick_Sort(int low, int high)
{
    int i=low,j=high;
    int temp=weight_array[i];
    while(i<j)
    {   //指向头尾的下标移动,数值大的网后移,小的前移
        while(i<j && temp<= weight_array[j])    //从尾部找到小于轴值的数
            j--;
        if(i<j)
        {   //找到小于轴值的数后将下标j的值移到i的位置
            weight_array[i]=weight_array[j];
            i++;
        }
        while(i<j && weight_array[i]<temp ) //从头部找到大于轴值的数
            i++;
        if(i<j)
        {   //找到小于轴值的数后将下标i的值移到j的位置
            weight_array[j]=weight_array[i];
            j--;
        }
    }
    weight_array[i]=temp;   //最后i==j时,将轴值放到此位置
    if(i>low)//对轴值左边的子序列进行递归快速排序
        Quick_Sort(low, i - 1);
    if(i<high)  //对轴值右边的子序列进行递归快速排序。
        Quick_Sort(j + 1, high);
}

void Graph::write_file()
{   //将深搜找到的路径写入到文件
    ofstream file_out("/home/lking/Desktop/Test_two/path.txt");
    if(!file_out)
        cout<<"open path.txt error"<<endl;
    vector<int>::iterator iter;
    int index,flag;
    for(unsigned k=0;k<weight_array.size();k++)
        {   //取拍好序的weight_array的值,查找其在way_number的下标即是此条路径的序号
            index=find(way_number.begin(),way_number.end(),weight_array[k])-way_number.begin();
            flag=index;
            for(;flag<index+1;flag++)
            {   //找到序号后将此条路径写入到文件,每次只写一条
                for(int j=0;j<10;j++)
                {   //路径共10个城市
                    if(all_way[flag][j]==all_way[flag][j-1])
                        break;//若出现相同城市表示路径到头,停止写入
                    file_out<<Vex[all_way[flag][j]]<<"\t";
                }
                file_out<<all_way[flag][10]<<"\n";  //写入权值
            }
    }
    file_out.close();
}

void Menu()
{
    cout<<"****************************************"<<endl;
    cout<<"*  Dijkstra-----------------------1    *"<<endl;
    cout<<"*  Floyd--------------------------2    *"<<endl;
    cout<<"*  All_path-----------------------3    *"<<endl;
    cout<<"*  Exit---------------------------0    *"<<endl;
    cout<<"*  PLEASE INPUT NUMBER TO EXE              *"<<endl;
    cout<<"****************************************"<<endl;
}

int main()
{

    Graph G;
    string str_one,str_two;
    int Ve_one,Ve_two;  //记录城市序号
    int high,i; //快速排序长度记录
    int distance[34],path[34];//
    int city_three_copy[34][34],path_Floyd[34][34];   //Floyd查找所需数组
    memset(path_Floyd,-1,sizeof(int)*34*34);  //将path_Floyd初始化为-1
    cout<<"请输入城市名:"<<endl;
   cin>>str_one>>str_two;
    G.check(str_one,str_two,Ve_one,Ve_two);
    Menu();
    for(;;)
    {
        cin>>i;
        //cout<<endl;
        switch(i)
        {
            case 1:
                system("clear");
                G.Dijkstra(&G,Ve_one,Ve_two,distance,path);
                G.SearchPath_Dijkstra(path,distance,Ve_one,Ve_two);
                break;
            case 2:
                system("clear");
                G.Floyd(city_three_copy,path_Floyd);
                G.SearchPath_Floyd(Ve_one,Ve_two,city_three_copy,path_Floyd);//system("clear");
                cout<<"相距"<<city_three_copy[Ve_one][Ve_two]<<endl;
                break;
            case 3:
                system("clear");
                G.DFS(Ve_one, Ve_two);
                high=G.get_SizeOfWeight();
                cout<<"共有"<<high<<"条路"<<endl;
                //G.show();
                G.Quick_Sort(0,high-1);
                //cout<<"======================================================"<<endl;
                //G.show();
                G.write_file();
                break;
            default:
                cout<<"谢谢使用";
                exit(0);
                break;
        }
        cout<<endl;
        Menu();
    }
    return 0;
}

画出该树中序和后序遍历的递归过程及堆栈变化情况
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
QQ号排序,冒泡,选择,快速,归并,希尔,堆
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

猜你喜欢

转载自blog.csdn.net/sinat_36742186/article/details/82590299