在java中生成无返回边的有向图

在java中生成无返回边的有向图,java,algorithm,graph,generator,Java,Algorithm,Graph,Generator,我试图制作一个有向图生成器,在LJF算法中使用它。问题是我不知道如何避免返回边(例如,如果我得到1->2,我不想得到2->1)。我只在if中做了一个声明,以避免同一节点的边缘(例如1->1)。另一个问题是,我的生成器有时会让一些节点没有任何边,但每个节点至少需要一条边。我想要达到的是类似于BST的东西,但没有规定最多有2条边,可以更多 public class Graph { private final int maxT = 3; private final int chance = 30;

我试图制作一个有向图生成器,在LJF算法中使用它。问题是我不知道如何避免返回边(例如,如果我得到1->2,我不想得到2->1)。我只在
if
中做了一个声明,以避免同一节点的边缘(例如1->1)。另一个问题是,我的生成器有时会让一些节点没有任何边,但每个节点至少需要一条边。我想要达到的是类似于BST的东西,但没有规定最多有2条边,可以更多

public class Graph {

private final int maxT = 3;
private final int chance = 30;  //chance to connect edges
Map<Task, List<Transmission>> tasks = new HashMap<Task, List<Transmission>>();

public Graph() {

    Random r = new Random();

    int range = r.nextInt(maxT) + 3; // number of nodes
    for(int i = 0; i<range; i++){
        List<Transmission> trans = new ArrayList<Transmission>();
        tasks.put(new Task(i), trans);
    }
    System.out.println("Number of tasks: " + tasks.size());

    for(Task key1 : tasks.keySet()){
        for(Task key2 : tasks.keySet()){
            if(key1 != key2 && r.nextInt(100) < chance)
                tasks.get(key1).add(new Transmission(key1,key2));
        }
    }

}

public void printGraph(){
    System.out.println("Generated graph:\n");
    for(Task key : tasks.keySet()){
        System.out.println(key.getId());
        for(Transmission ts : tasks.get(key)){
            System.out.println("\t" + ts.getT1().getId() + " -> " + ts.getT2().getId());
        }
    }       
}
}
我看到我新添加的列表中充满了空元素,我附加了任务类:

import java.util.Random;

public class Task extends Node{

Random r = new Random();
int tstart; // start time
int tend; // end time
int size; 
int deadline; 
public Task(int id) {
    super(id);
    tstart = r.nextInt(5);
    tend = r.nextInt(5);
    size = r.nextInt(10);
    deadline = r.nextInt(8);
}

public int getDeadline() {
    return deadline;
}
public int getTstart() {
    return tstart;
}
public int getTend() {
    return tend;
}
public int getSize() {
    return size;
}
}

==编辑====

现在我遇到了一个问题,我的发电机给了我我不想要的周期。所以,我又增加了一次进行传输的机会,但有时我会获得空闲节点或分离图形

List<Task> keys = new ArrayList<Task>(tasks.keySet());
    for(int i = 0; i < keys.size() - 1; i++){
        for(int j = i + 1; j < keys.size(); j++){
            if(r.nextInt(100) < chance && tasks.get(keys.get(i)).isEmpty())
                tasks.get(keys.get(i)).add(new Transmission(keys.get(i), keys.get(j)));}
    }
List keys=new ArrayList(tasks.keySet());
对于(int i=0;i
您可以使用由目标节点索引的映射,而不是每个
任务的
传输
列表。然后,您可以轻松地执行检查,确定是否已经存在后向边缘。此外,可以添加一个条件,以便在节点没有边时始终生成边:

public class Graph {

    private final int maxT = 3;
    private final int chance = 30;  //chance to connect edges
    Map<Task, Map<Task, Transmission>> tasks = new HashMap<>();

    public Graph() {

        Random r = new Random();

        int range = r.nextInt(maxT) + 3; // number of nodes
        for(int i = 0; i<range; i++){
            Map<Task, Transmission> trans = new HashMap<>();
            tasks.put(new Task(i), trans);
        }
        System.out.println("Number of tasks: " + tasks.size());

        for(Task key1 : tasks.keySet()){
            for(Task key2 : tasks.keySet()){
                if(key1 != key2
                        && !tasks.get(key2).containsKey(key1) // Don't generate an edge, if there already is a reverse edge
                        && (tasks.get(key1).isEmpty() // Always generate an edge, if there is none
                            || r.nextInt(100) < chance))
                {
                    tasks.get(key1).put(key2, new Transmission(key1,key2));
                }
            }
        }

    }

    public void printGraph(){
        System.out.println("Generated graph:\n");
        for(Task key : tasks.keySet()){
            System.out.println(key.getId());
            for(Transmission ts : tasks.get(key).values()){
                System.out.println("\t" + ts.getT1().getId() + " -> " + ts.getT2().getId());
            }
        }       
    }
}
公共类图{
私有最终整数最大值=3;
private final int chance=30;//连接边的机会
Map tasks=newhashmap();
公共图(){
随机r=新随机();
int range=r.nextInt(maxT)+3;//节点数

对于(int i=0;i而不是每个
任务
传输
列表,您可以使用由目标节点索引的映射。然后,您可以轻松执行检查,是否已经存在后向边。此外,您可以添加一个条件,以便在节点没有后向边时始终生成边:

public class Graph {

    private final int maxT = 3;
    private final int chance = 30;  //chance to connect edges
    Map<Task, Map<Task, Transmission>> tasks = new HashMap<>();

    public Graph() {

        Random r = new Random();

        int range = r.nextInt(maxT) + 3; // number of nodes
        for(int i = 0; i<range; i++){
            Map<Task, Transmission> trans = new HashMap<>();
            tasks.put(new Task(i), trans);
        }
        System.out.println("Number of tasks: " + tasks.size());

        for(Task key1 : tasks.keySet()){
            for(Task key2 : tasks.keySet()){
                if(key1 != key2
                        && !tasks.get(key2).containsKey(key1) // Don't generate an edge, if there already is a reverse edge
                        && (tasks.get(key1).isEmpty() // Always generate an edge, if there is none
                            || r.nextInt(100) < chance))
                {
                    tasks.get(key1).put(key2, new Transmission(key1,key2));
                }
            }
        }

    }

    public void printGraph(){
        System.out.println("Generated graph:\n");
        for(Task key : tasks.keySet()){
            System.out.println(key.getId());
            for(Transmission ts : tasks.get(key).values()){
                System.out.println("\t" + ts.getT1().getId() + " -> " + ts.getT2().getId());
            }
        }       
    }
}
公共类图{
私有最终整数最大值=3;
private final int chance=30;//连接边的机会
Map tasks=newhashmap();
公共图(){
随机r=新随机();
int range=r.nextInt(maxT)+3;//节点数
对于(inti=0;i来说,如果有(1->2),则很容易避免(2->1)EDE。对于每个边(x->y),假设x
向迭代添加顺序:

        List<Task> keys = new ArrayList<Task>(tasks.keySet());
    for(int i = 0; i < keys.size() - 1; i++){
        for(int j = i + 1; j < keys.size(); j++){
            tasks.get(i).add(new Transmission(keys.get(i), keys.get(j)));}
    }
List<T> keys = new ArrayList<>(map.keySet());
for (int i = 0; i < keys.size() - 1; i++) {
    for (int j = i + 1; j < keys.size(); j++) {
        make new Transmission(keys.get(i), keys.get(j));
    }
}
List keys=new ArrayList(map.keySet());
对于(int i=0;i
要解决完整的问题,您需要这样的算法:

  • N
    -一组未访问的顶点。所有顶点都在开始处
  • V
    -访问顶点集。开始时为空
  • N
    中获取随机顶点
    x
  • 从第二次迭代添加边(来自
    V
    ->
    x
    )的随机顶点
  • x
    添加到
    V
    并从
    N
    中删除
    x
  • 继续执行步骤3或退出
  • 您的图形将是无循环定向的。

    如果有(1->2),很容易避免(2->1)EDE。对于每个边(x->y),假设x 向迭代添加顺序:

            List<Task> keys = new ArrayList<Task>(tasks.keySet());
        for(int i = 0; i < keys.size() - 1; i++){
            for(int j = i + 1; j < keys.size(); j++){
                tasks.get(i).add(new Transmission(keys.get(i), keys.get(j)));}
        }
    
    List<T> keys = new ArrayList<>(map.keySet());
    for (int i = 0; i < keys.size() - 1; i++) {
        for (int j = i + 1; j < keys.size(); j++) {
            make new Transmission(keys.get(i), keys.get(j));
        }
    }
    
    List keys=new ArrayList(map.keySet());
    对于(int i=0;i
    要解决完整的问题,您需要这样的算法:

  • N
    -一组未访问的顶点。所有顶点都在开始处
  • V
    -访问顶点集。开始时为空
  • N
    中获取随机顶点
    x
  • 从第二次迭代添加边(来自
    V
    ->
    x
    )的随机顶点
  • x
    添加到
    V
    并从
    N
    中删除
    x
  • 继续执行步骤3或退出

  • 您的图形将是无循环的。

    您是否认为有一个严格的树,或者如果有两条从a到B的路径,例如1->2->4和1->3->4,它是否可以?更长的循环可以吗,比如说,1->2->3->->->->4->1?在NullPointerException行中:使用
    tasks.get(key.get(i))…
    而不是
    tasks.get(i)…
    @Beethoven是的,它是有效的,很明显,idk为什么我没有看到它。不管怎样,你知道在这个例子中如何避免自由节点吗?@Beethoven,因为这一个给出了循环,所以我又加了一次机会来做一个transmission@Buszman如果传输列表仍然为空,则必须绕过随机,如下所示:
    if(tasks.get(keys.get(i)).isEmpty()| | r.nextInt(100)
    你想有一个严格的树吗,或者如果从a到B有两条路径,例如1->2->4和1->3->4,它可以吗?在NullPointerException行中使用
    tasks.get(key.get(i))…
    而不是
    tasks.get(i)可以吗…
    @Beethoven是的,它是有效的,很明显,idk为什么我没有看到它。不管怎样,你知道在这个例子中如何避免自由节点吗?@Beethoven,因为这一个给出了循环,所以我又加了一次机会来做一个transmission@Buszman如果传输列表仍然为空,则必须绕过随机,如下所示:
    if(tasks.get(keys.get(i)).isEmpty()| | r.nextInt(100)
    这似乎不错,但我的程序的下一步是在处理器上调度此任务,我不知道如何引用这一秒Map@Buszman如果需要
    任务的
    传输
    ,可以使用
    tasks.get(Task).values()
    ,即从内部映射获取值的集合(
    Transmission
    s)。这是否回答了问题