【问题标题】:Unable to create Adjacency List for an undirected Graph using C无法使用 C 为无向图创建邻接表
【发布时间】:2015-02-21 10:08:45
【问题描述】:

我面临一个很长一段时间以来一直无法解决的问题。 我得到了一个如下图,在一个 M x N 矩阵中:

2 2
a b
a c

注意 我将上面的图解释为一个矩阵,只包含非对角边。

这里第一行分别代表M和N的值。 该图仅沿垂直或相邻方向连接,即上、下、左和右。对角线边缘不存在。

为了找到图的邻接表(这里需要输出):

a-b-c
b-a-c
c-a-b

我在代码中遵循的步骤:

1.将M x N矩阵读入二维数组。

2.创建图的唯一顶点列表作为Unode[arrmax]。

3.对于矩阵的每个元素,如果字符与唯一顶点列表的元素匹配,我调用了修改邻接列表过程,该过程搜索相关矩阵顶点的邻居并填充/附加到找到不同节点时的邻接列表。

  1. 它将 i、j、M、N、AdjList、列表中元素的数量作为参数并进行更改。

5.我将节点列表保持为全局以便于修改。

6.接下来我打算使用生成的邻接表在DFS程序中使用并找到DFS林。

问题陈述:

输入由大小为 M X N 的网格组成。网格中的每个单元格 包含英文字母的小写字母。以自然的方式, 细胞有两种类型:边界细胞和内部细胞。每个 网格中的内部单元格在左侧之一中有四个邻居, 右、上、下方向。一串字符可以由 从任何单元格开始并通过邻居遍历网格。 您必须根据以下内容打印所有可能的字符串 约束:

**No two characters in a string can be same 
**No two strings can be same in the final output 
**The strings should be printed in alphabetically sorted order.
INPUT: 

First line contains two integers M and N
Next M lines contains N space separated characters each

OUTPUT:

Print all possible strings in sorted order and obeying the above constraints.

INPUT SIZE:

1 <= M, N <= 20

SAMPLE INPUT:

2 2
a b
a c

SAMPLE OUTPUT:

a ab abc ac acb b ba bc bca c ca cb cba

[更新]: 完全重新设计了代码,使用了图形节点的结构,以及一个用于处理索引的结构。 然而我得到的结果:

a--b-a
b--a
a
c--a

我的代码[相关部分]:

    #include <stdio.h>
#include<stdlib.h>
#include<string.h>
#define ADJMAX 20
#define arrmax 400

typedef struct uniq_node{
    char ch;
    char AdjList[ADJMAX];
    int numofelem;
    int visited;
}unode;

unode Ulist[arrmax];
int uniq_tot=0;

typedef struct index
{
    int i,j;
}Ind;

Ind indx;

int charcomp(char sch,char arr[],int arrlim);
void adjModify(unode*,char*,int,int,Ind);
int chIndex(int,int,int,int);

int main(void) {
    int mvar,nvar;
    char str[15],*token;
    long integer;

    /*To scan the values of M & N*/
    scanf("%d %d\n",&mvar,&nvar);
    int iter,iterv,jterv;

    /*To create the character matrix of M x N*/
    char cmat[mvar][nvar];


    /*Initializing the unique nodes list*/


    /*To read-in the matrix from the stdin:-A LOT OF HARD WORK*/
    for(iterv=0;iterv<mvar;iterv++)
    {
            fgets(str,50,stdin);
            jterv=0;
            token=strtok(str," ");
            while(token)
            {
                    /*Assigning value to the character matrix*/
                    cmat[iterv][jterv]=*token;
                    /*Code to populate the list of unique elements*/
                    if(charcomp(*token,Ulist[uniq_tot].AdjList,uniq_tot)==3)
                    {
                        Ulist[uniq_tot].ch=*token;
                        uniq_tot++;
                        Ulist[uniq_tot].numofelem=1;
                        Ulist[uniq_tot].AdjList[0]=*token;
                        //Ulist[uniq_tot].visited=0;
                    }
                    jterv++;
                    token = strtok(NULL, " ");
            }
    }
    /*To populate the adjacency lists */
    char ch;
    for(iterv=0;iterv<mvar;iterv++)
    {
        for(jterv=0;jterv<nvar;jterv++)
        {
            ch=cmat[iterv][jterv];
            indx.i=iterv;
            indx.j=jterv;
            for(iter=0;iter<uniq_tot;iter++)
            { 
                if(ch==Ulist[iter].ch)
                break;
            }
            adjModify(&Ulist[iter],(char*)cmat,mvar,nvar,indx); 
        }
    }


    /*for(iter=0;iter<uniq_tot;iter++)
    {
        printf("%c",Ulist[iter].ch);
            printf("\n%s\n",Ulist[iter].AdjList);
        for(iterv=0;iterv<Ulist[iter].numofelem;iterv++)
        {
            printf("-%c",Ulist[iter].AdjList[iterv]);
        }
        printf("\n");
    }*/

    return 0;
}

int chIndex(int i,int j,int mvar,int nvar)
{
    return (i>=0 && i<mvar && j>=0 && j<nvar);
}

void adjModify(unode* Unode,char* mat,int mvar,int nvar,Ind mind)
{
    int idum,jdum;
    if(chIndex(mind.i,mind.j-1,mvar,nvar))
        {
            idum=mind.i;
            jdum=mind.j-1;
            if(charcomp(*(mat+idum*nvar+jdum),Unode->AdjList,Unode->numofelem)==3)
                {
                    ++Unode->numofelem;
                Unode->AdjList[Unode->numofelem]=*(mat+idum*nvar+jdum);
                printf("\nI'm here in coord:(%d,%d), with element: %c, and AdjList: %s for character: %c",idum,jdum,*(mat+idum*nvar+jdum),Unode->AdjList,Unode->ch);
                }
        }
    if(chIndex(mind.i,mind.j+1,mvar,nvar))
        {
            idum=mind.i;
            jdum=mind.j+1;
            if(charcomp(*(mat+idum*nvar+jdum),Unode->AdjList,Unode->numofelem)==3)
                {
                    ++Unode->numofelem;
                Unode->AdjList[Unode->numofelem]=*(mat+idum*nvar+jdum);
                printf("\nI'm here in coord:(%d,%d), with element: %c, and AdjList: %s for character: %c",idum,jdum,*(mat+idum*nvar+jdum),Unode->AdjList,Unode->ch);
                }
        }
    if(chIndex(mind.i-1,mind.j,mvar,nvar))
        {
            idum=mind.i-1;
            jdum=mind.j;
            if(charcomp(*(mat+idum*nvar+jdum),Unode->AdjList,Unode->numofelem)==3)
                {
                    ++Unode->numofelem;
                Unode->AdjList[Unode->numofelem]=*(mat+idum*nvar+jdum);
                printf("\nI'm here in coord:(%d,%d), with element: %c, and AdjList: %s for character: %c",idum,jdum,*(mat+idum*nvar+jdum),Unode->AdjList,Unode->ch);
                }
        }
    if(chIndex(mind.i+1,mind.j,mvar,nvar))
        {
            idum=mind.i+1;
            jdum=mind.j;
            if(charcomp(*(mat+idum*nvar+jdum),Unode->AdjList,Unode->numofelem)==3)
                {
                    ++Unode->numofelem;
                Unode->AdjList[Unode->numofelem]=*(mat+idum*nvar+jdum);
                printf("\nI'm here in coord:(%d,%d), with element: %c, and AdjList: %s for character: %c",idum,jdum,*(mat+idum*nvar+jdum),Unode->AdjList,Unode->ch);
                }
        }
}

/*Comparison routine*/
int charcomp(char fchar,char arr[],int ucindex)
{
    int ivar;
    for(ivar=0;ivar<ucindex;ivar++)
    {
        if(arr[ivar]==fchar)
            return;
    }

        return 3;

}

【问题讨论】:

  • 对不起,矩阵是什么? 2 2 a b a c 在我看来不像矩阵。这代表什么?这看起来像是创建一个简单图形的大量代码。您还说它是单向的,那为什么您的链接看起来像是定向的?
  • 2 2 分别代表M和N。由于 No._of_edges/2=no。独特的顶点,因此我将其视为无向的。此外,对于重复节点,我使用了相同的邻接列表。
  • 当你说邻接矩阵时,我期望像这样en.wikipedia.org/wiki/Adjacency_matrix我不知道如何解释你的。
  • 对不起,如果我不明确,但我打算创建一个邻接列表。这是一个邻接矩阵表示,我没有使用它,因为我发现 DFS 的算法更方便为 Adj List 编写代码。另外,我认为我的比较例程有缺陷,和/或某个地方的空白正在蔓延到 Adj清单,我相信一双新鲜的眼睛会成功:-)
  • 没问题,还有一件事,就是这个“a->b->c b->a->c c->a->b”的输入,而你正在尝试解析那个确切的文字?箭头是否暗示方向性?

标签: c algorithm matrix


【解决方案1】:

我认为您可以跳过为二维数组中的每个元素创建单独的节点。拥有 2D 阵列意味着结构化连接。当它开始变大时,遍历所有这些元素可能会变得很麻烦。

我推荐的方法如下:

  1. 扫描矩阵并提取唯一节点。即从扫描开始,然后有一个简单的列表 a、b、c(您需要对它们进行排序)。

  2. 为每个唯一节点创建一个结构,该结构包含您当前拥有的路径数和一个用于存储每个路径的 char 数组数组。即 char** myArray={{a},{ab},{abc },{ac},{acb}} 将是一个(当你开始时当然是未知的)。

  3. 循环遍历您的唯一节点,并一一找到二维数组中的位置。不要保存它们,只需要一个一个地浏览它们并执行扫描功能以查找它们的所有路径。

  4. 扫描函数应该是递归的,这样它就可以在检查每条可能的路径时尽可能地走多远(递归将帮助您检查遍历的每个节点的每个方向)。跟踪您去过的地方,并随时检查您是否还没有遇到过该角色。

  5. 当你不能再进一步时,确保该字符串尚未被包含,如果它继续到下一个路径,如果没有将它添加到列表中。

【讨论】:

  • 当然,如果部分目标是创建和使用邻接列表,这将无济于事。
  • 好的,所以递归扫描函数,我将作为 DFS 实现,必须处理每个唯一节点一次,即,必须从第一个唯一节点的索引,然后是第二个..?我应该通过捕获堆栈的状态还是仅在过程结束时收集每个步骤的字符串?还有一件事,我在处理字符的字符时遇到了问题,这些字符也用于存储由遍历的路径构建的字符串。那里有任何策略/代码吗?真的,非常感谢你的帮助 :-) 真的很感激,当我获得足够的声誉时会投票。
  • 对于起始位置,我喜欢先拥有唯一的 char 数组。然后您搜索二维数组以查找该唯一字符的所有实例。您不需要一次存储所有这些索引,只需在找到每个索引时开始搜索即可。然后在各个方向递归搜索。您需要随时存储路径,因为(1)您采取的每一步都需要检查您是否已经击中该字符(2)一旦您击中了您已经到达的字符,请检查您没有已经有了那个字符串。如果您没有该字符串,请保存它,如果您没有并继续。
  • 对于操作 char 数组,分配一个大小与唯一字符数匹配的数组(因为您不能在数组中多次使用相同的 char)。重新使用此 char 数组进行搜索以存储当前路径(在递归函数的每次返回中删除最后一个数组)。找到路径并想要存储它后,分配另一个需要存储大小的数组,并将其添加到该唯一节点结构的 char 指针列表中。
【解决方案2】:

这是我在 c++ 中的代码,没有任何可以在 c 中工作的库,但你只需要在 c 中使用 printf 而不是 cout,而不是 class 使用 struct 就可以了。我还为广度优先遍历编写代码,见下文。 并包含头文件

// #include <stdio.h>
//#include<stdlib.h>
#include<iostream
using namespace std;
class Node {
public:
    int data;
    Node* next;

    Node(int data) {
        this->data=data;
        this->next=NULL;
       // cout<<"from node file"<<endl;
    }


};



class Queue {
    Node * head;
    Node * tail;
    int length;

    public:
        Queue() {
            head=NULL;
            tail=NULL;
            length=0;
        }

        bool isEmpty() {
            return length==0;
        }

        int size() {
            return length;
        }

        int front() {
            if(head==NULL) {
                cout<<"Empty Queue"<<endl;
                return 0;
            }
            return head->data;
        }

        void enqueue(int element) {
            Node *  newNode =new Node(element);
            if(head==NULL) {
                head=newNode;
                tail=newNode;
            }else{
                tail->next=newNode;
                tail=newNode;
            }
            length++;
        }

        int dequeue() {
            if(head==NULL) {
                cout<<"Empty queue"<<endl;
                return 0;
            }
            int output= head->data;
            Node * temp=head;
            head=head->next;
            temp->next=NULL;
            delete temp;
            length--;
            return output;
        }
};

class AdjList{
public:
    Node * head;
    AdjList() {
            head=NULL;
             //cout<<"from adlist"<<endl;
    }

    void add (int data) {
        Node * newNode=new Node(data);
        if(head==NULL) {
                head=newNode;
        }else {
                Node* temp=head;
                while(temp->next!=NULL) {

                    temp=temp->next;
                }
                temp->next=newNode;
        }
    }

};

class Graph{
public:
    int v;
    AdjList* adjList;


        Graph(int v) {
            this->v=v;
            adjList=new AdjList[v];
        }

        void addEdge(int src, int dest) {
                adjList[src].add(dest);
                ///for bidrectional add below code
                //adjList[dest].add(src);
        }



    void print(){
        for(int i=0;i<v;i++){
            Node *temp = adjList[i].head;
            cout << i << " -> ";
            while(temp != NULL)
            {
                cout << temp->data << " ";
                temp = temp->next;
            }
            cout << endl;
        }
    }

     void bfs(int src) {
        // using a queue also in this file how to add queue structure
        Queue q;
        bool* visited=new bool [v]{0};
        q.enqueue(src);
        visited[src]=true;
        while(!q.isEmpty()) {
            int node= q.front();
            cout<<node<<"  ";
            q.dequeue();
            Node *temp = adjList[node].head;
            while(temp!=NULL){
                if(!visited[temp->data]) {
                        q.enqueue(temp->data);
                        visited[temp->data]=true;
                }
               // cout<<"data "<<temp->data;
                temp=temp->next;
             /// how to traverse
            }
        }
    }
};

int main(){

   Graph g(6);

       g.addEdge(0, 1);
    g.addEdge(0, 2);
    g.addEdge(1, 3);
    g.addEdge(2, 3);
    g.addEdge(3,4);
   g.addEdge(4,5);

 g.bfs(0);

  // g.print();
    return 0;
}

【讨论】:

  • 更喜欢准确地解释和回答问题,而不是给出通用案例的完整代码。谢谢
猜你喜欢
  • 2018-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多