头歌编程题实训-图

该文章已生成可运行项目,

第1关:迷宫问题

int DFS(int k,int (*a)[3])
{//深度搜索第k层,k:当前路口
/**************begin************/
    if(k==m) { //到达出口
        tag=1;
        return 0;
    }
    for(int i=0;i<3;i++) {//遍历向左路口、向前路口、向右路口
        if(0!=a[k][i]&&tag!=1) {//如果当前路口有通路,并且没有走过
            DFS(a[k][i],a);//进入下一个路口 ,递归
        }
    }
    return 0;
    /**************end************/
}

第2关:基于Dijsktra算法的最短路径求解

void ShortestPath_DIJ(AMGraph G, char V)
{//用Dijkstra算法求有向网G的v0顶点到其余顶点的最短路径
/**************begin************/
    int i,n,v,Min,w;
    int S[MVNum];           //S[i]记录从源链0到终点
    n=G.vexnum;                         //N列表中的项目数
    int v0=LocateVex(G,V);     
    for(v=0;v<n;++v)      
    {
        S[v]=false;                   //首为空
        D[v]=G.arcs[v0][v];             //分为不同终端的短期数据库的初始初始化更改为右上角的值
        if(D[v]<MaxInt)
            Path[v]=v0;                  //V0之间进行选择,并将v的第一个要求设置为V0
        else
            Path[v]=-1;                //如果v0和v0之间没有差异,则v0的第一个要求设置为1
    }//for
    S[v0]=true;                     //将0添加到S
    D[v0]=0;                            
    for(i=1;i<n;++i)       
    {
        Min=MaxInt;
        for(w=0;w<n;++w)
            if(!S[w]&&D[w]<Min)    
            {
                v=w;
                Min=D[w];
            }
        S[v]=true;                          //添加S
        for(w=0;w<n;++w)  
            if(!S[w]&&(D[v]+G.arcs[v][w]<D[w]))
            {
                D[w]=D[v]+G.arcs[v][w];     //更新D[w]
                Path[w]=v;                     //先前更改w的要求是v
            }//if
    }//for
    /**************end************/
}

第3关:六度空间理论

float SixDegree_DIJ(int G[][MAXSIZE], int n, int start) 
{//通过这个“新的开始”,我们可以计算法律系统中六个空时间点的数量,而开始是交换机指定时间点的第一级
/**************begin************/
    bool S[MAXSIZE];                     //S[]是按以下顺序开始的最短时间
    int D[MAXSIZE];                      //D[]是以下序列到达起点的最短时间
    for (int i=0;i<n;i++) {      
        S[i]=false;
        D[i]=INFINITE;
    }
    S[start]=true;                        //将起点添加到S
    D[start]=0;                            
    for (int i=0;i<n;i++) {          
        if (G[start][i]!=0)
            D[i]=G[start][i];
    }
//初始区域完成或完成后,在相同的环境中启动事件,然后要求系统启动到一定的最小时间长度,然后将其添加到S板
    for (int i=0;i<n-1;i++) {
        int v=FindMinPath(S, D, n);
        if (v==-1) break;
        S[v]=true;                        
        for (int w=0;w<n;w++) {        
            if (!S[w]&&D[w]>D[v]+G[v][w]) {
                D[w]=D[v]+G[v][w];        //更新D[w]
            }
        }
    }
//已请求点开始图[]中剩余短周期的数量,剩余短周期数量现在比其他两个短周期数量少,可以作为相关短周期的百分比列
    float count=1;
    for (int i=0;i<n;i++) {
        if (D[i]<=6)
            count++;
    }
    return count/n;
    /**************end************/
}

 第4关:基于邻接表的新顶点的增加

int InsertVex(ALGragh &G)
{//在以邻接表形式存储的无向图G上插入顶点v
/**************begin************/
    if((G.vexnum+1)>MVNum) return ERROR;    //判断插入操作是否合法
    G.vexnum++;                           //增加图G的顶点数量
    cin>>G.vertices[G.vexnum-1].data;     //存入新结点对应的链表的头结点数据域
    G.vertices[G.vexnum-1].firstarc=NULL;    //指针域赋值为NULL
    return OK;
    /**************end************/
}

第5关:基于邻接矩阵的新顶点的增加

int InsertVex(AMGragh &G)
{//在以邻接矩阵形式存储的无向图G上插入顶点
/**************begin************/
    if((G.vexnum+1)>MVNum) return ERROR;    //判断插入操作
    G.vexnum++;                             //增加图G的顶点数量
    cin>>G.vexs[G.vexnum];                  //将新顶点存入表
    for(int k=0;k<G.vexnum;k++)             //邻接矩阵相应位置的元素置为0
        G.arcs[G.vexnum][k]=G.arcs[k][G.vexnum]=0;
    return OK;
    /**************end************/
}

第6关:基于邻接表的顶点的删除

int DeleteVex(ALGragh &G)
{//删除G中顶点f及其相关的弧
/**************begin************/
    int i,f;                  //f代表删除的顶点编号
    cin>>f;
    DeleteAdjList(G.vertices[f-1]);       //删除指定顶点链表上的边结点
    for(i=f;i<G.vexnum;i++)      //把f的顶点信息删除,后面顶点向前移动
    {
        G.vertices[i-1]=G.vertices[i];
    }
    G.vexnum--;                  //顶点数减1
    for(i=0;i<G.vexnum;i++)           //遍历图G,删除顶点f相关的边
    {
        VNode p=G.vertices[i];     //p用于指向当前结点的前驱
        VNode q=G.vertices[i];     //q用于指向当前结点
        if(p.firstarc->data==f)                 //如果当前结点的第一条边关联的结点为f,则直接删除该边
        {
            ArcNode *t=G.vertices[i].firstarc;
            G.vertices[i].firstarc=t->nextarc;
            delete t;
            G.arcnum--;
            continue;
        }
        q.firstarc=q.firstarc->nextarc;            //继续比较后面的边结点
        while(q.firstarc)
        {
            if(q.firstarc->data==f)                  //存在与f相关的边,则删除该边
            {
                p.firstarc->nextarc=q.firstarc->nextarc;
                delete q.firstarc;
                G.arcnum--;
                break;
            }
            p.firstarc=q.firstarc;                 //没找到与f关联的边,指针后移
            q.firstarc=q.firstarc->nextarc;
        }
    }
    return OK;
    /**************end************/
}

第7关:基于邻接表的新边的增加

int InsertArc(ALGragh &G)
{//在以邻接表形式存储的无向图G上插入边
/**************begin************/
    int h,k;
    cin>>h>>k;                       //输入一条边的两个顶点h和k
    ArcNode* p1=new ArcNode;         //生成边结点*p1
    p1->adjvex=h-1;                  //邻接点序号为h-1,即顶点在G.vertices中的序号
    p1->data=k;
    p1->nextarc=G.vertices[h-1].firstarc;   //将新结点*p1插入顶点的边表头部
    G.vertices[h-1].firstarc=p1;
    ArcNode* p2=new ArcNode;         //生成边结点*p2
    p2->adjvex=k-1;                  //邻接点序号为k-1,即顶点在G.vertices中的序号
    p2->data=h;
    p2->nextarc=G.vertices[k-1].firstarc;   //将新结点*p2插入顶点的边表头部
    G.vertices[k-1].firstarc=p2;
    return OK;	
      /**************end************/
}

第8关:基于邻接矩阵的新边的增加

int InsertArc(AMGragh &G)
{//在以邻接矩阵形式存储的无向图G上插入边
/**************begin************/
    int f,g;
    cin>>f>>g;
    G.arcs[f-1][g-1]=G.arcs[g-1][f-1]=1;     //在邻接矩阵上增加对应的边
    G.arcnum++;
    return OK;
    /**************end************/
}

第9关:基于邻接表的边的删除

int DeleteArc(ALGragh &G)
{//在以邻接表形式存储的无向图G上删除边
/**************begin************/
	int f,g;
    cin>>f>>g;       //f和g代表删除的边所依附的两个顶点
    ArcNode *q,*p;
    p=G.vertices[f-1].firstarc;   //指针p初始化指向顶点vf-1的边表头部
    q=p;                     //q用于指向*p的前驱结点
    while(p->data!=g)     //遍历链表寻找顶点g
    {
        q=p;
        p=p->nextarc;
    }
    if(q==p)       //如果与顶点vf-1相连的第一个边表就是待删除顶点
    {
        G.vertices[f-1].firstarc=p->nextarc;
        delete p;
        G.arcnum--;     //边的数目减1
    }
    else
    {
        q->nextarc=p->nextarc;
        delete p;
        G.arcnum--;
    }
    p=G.vertices[g-1].firstarc; //指针p初始化指向顶点vg-1的边表头部
    q=p;         //q用于指向*p的前驱结点
    while(p->data!=f)   //遍历链表寻找顶点f
    {
        q=p;
        p=p->nextarc;
    }
    if(q==p)    //如果与顶点vg-1相连的第一个边表就是待删除边
    {
        G.vertices[g-1].firstarc=p->nextarc;
        delete p;
        G.arcnum--;       //边的数目减1
    }
    else
    {
        q->nextarc=p->nextarc;
        delete p;
        G.arcnum--;
    }
    return OK;
    /**************end************/
}

第10关:基于邻接矩阵的边的删除

int DeleteArc(AMGragh &G)
{//在以邻接矩阵形式存储的无向图G上删除边
/**************begin************/
    int f,g;        //f和g代表删除的边所依附的两个顶点
    cin>>f>>g;
    G.arcs[f-1][g-1]=G.arcs[g-1][f-1]=0;    //在邻接矩阵上删除边
    G.arcnum--;      //边数减1
    return OK;
    /**************end************/
}

第11关:基于邻接表的深度优先遍历

void DFS(ALGraph G,int v,SqStack S)
{
/**************begin************/
    InitStack(S);    //构造一个空栈实现非递归过程
    Push(S,v);       //顶点v进栈
    int cnt=0,k;
    ArcNode *p;
    while(!StackEmpty(S))
    {
        Pop(S,k);                 //栈顶元素k出栈
        if(!visited[k])
        {
            cnt++;
            if(cnt<G.vexnum)      //访问第k个顶点
                    cout<<k<<" ";
                else
                    cout<<k<<endl;
            visited[k]=true;
        }
        p=G.vertices[k].firstarc;  //p指向k的边链表的第一个边结点
        while(p!=NULL)             //边结点非空
        {
            if(!visited[p->data])  //如果p->data未被访问,p->data进栈
                Push(S,p->data);
            p=p->nextarc;          //p指向下一个边结点
        }
    }//while
    /**************end************/
}

第12关:最长的最短路径的求解

void ShortPathMAX(AMGraph G,int v0)
{//用Dijkstra算法求解
/**************begin************/
    bool* S=new bool[G.vexnum+1];    //顶点集S,初始值为false
    int* Path=new int[G.vexnum+1];
    int* D=new int[G.vexnum+1];      //保存v0到其他所有顶点的最短路径
    int i,j,Min,Min_j,k,Max,Max_j;
    for(i=1;i<=G.vexnum;i++) {       //初始化
        S[i]=false;                 
        D[i]=G.arcs[v0][i];          //将v0到各个终点的最短路径长度初始化为弧上的权值
        if(D[i]==MaxInt)
            Path[i]=ERROR;           //如果v0和v之间无弧,则将v的前驱置为ERROR
        else
            Path[i]=v0;              //如果v0和v之间有弧,则将v的前驱置为v0
    }
    S[v0]=true;                      //将v0加入S
    D[v0]=0;                       
    //主循环,每次求得v0到某个顶点v的最短路径,将v加到S集
    for(i=1;i<=G.vexnum;i++) {       //依次进行计算其余顶点
        Min=MaxInt;
        for(j=1;j<=G.vexnum;j++) {
            if(!S[j]&&D[j]<Min) {    //选择一条当前的最短路径,终点为Min_j
                Min_j=j;
                Min=D[j];
            }
        }
        S[Min_j]=true;               //将Min_j加入S
        for(k=1;k<=G.vexnum;k++) {   //更新从v0出发到集合V-S上所有顶点的最短路径长度
            if(!S[k]&&(D[Min_j]+G.arcs[Min_j][k]<D[k])) {
                D[k]=D[Min_j]+G.arcs[Min_j][k];      //更新D[k]
                Path[k]=Min_j;                       //更新k的前驱为Min_j
            }
        }
        //设距离顶点v0的最短路径长度最大的一个顶点为Max_j
        Max=0;
        for(i=1;i<=G.vexnum;i++) {
            if(Max<D[i]) {
                Max=D[i];
                Max_j=i;
            }//if
        }//for
        cout<<Max_j<<endl;      //最短路径最长的顶点编号
        cout<<Max<<endl;        //两点的最短距离
    }//for
    /**************end************/
}

第13关:基于深度优先搜索的两顶点路径存在与否的判断

int PathDFS(ALGragh G,int i,int j)
{
/**************begin************/
    if(i==j) return OK;          //递归结束的条件,首尾相遇,存在路径
    else
    {
        visited[i]=true;         //顶点i访问标志为true
        ArcNode *p;
        for(p=G.vertices[i].firstarc;p;p=p->nextarc,level--)
        {
            level++;             //递归层加1
            int k=p->adjvex;
            if(!visited[k]&&PathDFS(G,k,j))
                return OK;       //i下游的顶点到j有路径
        }
    }
    if(level==1) return ERROR;       //i到j没有路径
    return ERROR;
    /**************end************/
}

第14关:基于邻接表的长度为k的简单路径的求解

int CreateUDG(ALGragh &G,int vexnum,int arcnum,char ch[])
{//采用邻接表表示法,创建无向图G
/**************begin************/
    G.vexnum=vexnum;     //输入总顶点数
    G.arcnum=arcnum;     //输入总边数
    if(G.vexnum>MVNum) return ERROR;   //超出最大顶点数则结束函数
    for(int i=0;i<G.vexnum;i++) {      //构造表头结点表
        G.vertices[i].data=ch[i];      //输入顶点值
        G.vertices[i].firstarc=NULL;   //初始化表头结点的指针域为NULL
    }
    for(int j=0;j<G.arcnum;j++) {      //遍历图中所有边
        char h,p;
        cin>>h>>p;                     
        ArcNode* p1=new ArcNode;       //创建一个新的ArcNode对象p1,表示从顶点h到顶点p的边
        int pos2=Locate(ch,p);         //在ch数组中找到顶点p的位置pos2
        p1->adjvex=pos2;               
        p1->data=p;                    
        int pos1=Locate(ch,h);         //在ch数组中找到顶点h的位置pos1
        p1->nextarc=G.vertices[pos1].firstarc; //将p1插入到顶点h的边链表的头部
        G.vertices[pos1].firstarc=p1;  //更新顶点h的第一条边为p1
        ArcNode* p2=new ArcNode;       //表示从顶点p到顶点h的边
        p2->adjvex=pos1;               
        p2->data=h;                    
        p2->nextarc=G.vertices[pos2].firstarc; //将p2插入到顶点p的边链表的头部
        G.vertices[pos2].firstarc=p2;  //更新顶点p的第一条边为p2
    }
      return OK;
      /**************end************/
}

第15关:基于邻接矩阵的顶点的删除

int DeleteVex(AMGragh &G)
{
/**************begin************/
    int i,j,f;                      //f代表要删除的顶点编号
    cin>>f;
    for(i=f-1;i<G.vexnum-1;i++) {   //从目标顶点所在行开始,用下一行的边的权值逐行覆盖上一行边的权值
        for(j=0;j<G.vexnum;j++) { 
            G.arcs[i][j]=G.arcs[i+1][j];
        }
    }
    G.vexnum--;                     //图的顶点数减1
    for(i=0;i<G.vexnum;i++){        //从目标顶点所在列开始,用后一列的边的权值逐列覆盖前一列边的权值
        for(j=f-1;j<G.vexnum;j++){
            G.arcs[i][j]=G.arcs[i][j+1];
        }
    } 
    for(i=f;i<=G.vexnum;i++)         //更新顶点表
        G.vexs[i]=G.vexs[i+1];
    return OK;
      /**************end************/
}

本文章已经生成可运行项目
### 关于栈和队列的编程题与客观题 #### 编程题示例 1. **逆波兰表达式求值** 使用栈来计算逆波兰表达式的值。输入是一个字符串数组表示的逆波兰表达式,返回其整数值。 ```python def evalRPN(tokens): stack = [] for token in tokens: if token in "+-*/": b = stack.pop() a = stack.pop() if token == '+': stack.append(a + b) elif token == '-': stack.append(a - b) elif token == '*': stack.append(a * b) elif token == '/': stack.append(int(a / b)) else: stack.append(int(token)) return stack[0] ``` 2. **括号匹配验证** 给定一个只包含 `'('` 和 `')'` 的字符串,判断括号是否合法配对。 ```python def isValid(s): stack = [] mapping = {")": "(", "}": "{", "]": "["} for char in s: if char in mapping.values(): stack.append(char) elif char in mapping.keys(): if not stack or mapping[char] != stack.pop(): return False return not stack ``` 3. **队列的最大值** 设计一个支持在 O(1) 时间复杂度下获取最大值的队列类。 ```python import collections class MaxQueue: def __init__(self): self.queue = collections.deque() self.max_queue = collections.deque() def max_value(self): return self.max_queue[0] if self.max_queue else -1 def push_back(self, value): while self.max_queue and self.max_queue[-1] < value: self.max_queue.pop() self.max_queue.append(value) self.queue.append(value) def pop_front(self): if not self.queue: return -1 result = self.queue.popleft() if result == self.max_queue[0]: self.max_queue.popleft() return result ``` --- #### 客观题示例 1. 下面哪一项描述不符合栈的特点? - A. 后进先出 (LIFO) - B. 插入删除操作仅在一端进行 - C. 可以随机访问任意位置的元素[^5] - D. 常见应用有函数调用堆栈、浏览器回退功能 2. 对于队列的操作特性,下面哪个选项是错误的? - A. 队列遵循先进先出原则 (FIFO)[^6] - B. 删除操作发生在队 - C. 插入操作可以在两端发生 - D. 应用场景包括打印任务调度、消息传递系统 3. 如果一个栈初始为空,依次执行以下操作:push(1),push(2),pop(),push(3),那么此时栈顶元素是什么? - A. 1 - B. 2 - C. 3 - D. 栈为空 4. 在循环队列中,假设队首指针为 front,队尾指针为 rear,则下列哪种情况表明队列为满状态? - A. `(rear + 1) % size == front` - B. `front == rear` - C. `rear + 1 == front` - D. `front - 1 == rear` 5. 已知某程序使用了一个固定大小为 N 的数组模拟栈,当 top=-1 表示栈空时,top=N-1 则表示什么? - A. 栈已满 - B. 栈仍有一半空间可用 - C. 栈处于中间状态 - D. 栈无法继续压入新元素[^7] --- ####
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值