Breadth first search simple improvement - breadth-first-search

In most resources implementation of BFS is like this(this is geeks for geeks implementation):
void findpaths(vector<vector<int> >&g, int src,
int dst, int v)
{
// create a queue which stores
// the paths
queue<vector<int> > q;
// path vector to store the current path
vector<int> path;
path.push_back(src);
q.push(path);
while (!q.empty()) {
path = q.front();
q.pop();
int last = path[path.size() - 1];
// if last vertex is the desired destination
// then print the path
if (last == dst)
printpath(path);
// traverse to all the nodes connected to
// current vertex and push new path to queue
for (int i = 0; i < g[last].size(); i++) {
if (isNotVisited(g[last][i], path)) {
vector<int> newpath(path);
newpath.push_back(g[last][i]);
q.push(newpath);
}
}
}
the above implementation suggests that we first add the neighbors to the queue then we will check it that it is our destination or not.
but we can simply check the neighbor is the destination or not when adding the neighbor to the queue (instead of checking it when it is that node's turn) although it is a very minor improvement, it is better than the last one. so why everyone use the previous method for implementing BFS?

Related

how to Recreate boundary from array of junctions in imagej - fiji?

I am detecting and storing the boundary of a sandpile to an array and then save it as a text file for later use. the way i stored the boundary as text file is by using the wand tool, then getting the properties of the selection which gives me a table. Then converting table to array and finally storing it as text file.
after doing so i noticed that the above mentioned table only has the (X,Y) coordinates of the "junctions" on the boundary and not every pixel of the boundary.
Now when i say later use, i want to smooth out the boundary with various methods and redraw it but i am stuck at how to go from junctions to complete boundary. Below is my attempt to do it but i am seeing heavy ram usage just after the output is printed.
Thanks for any help and your time.
X=newArray(1,5,5,10);
Y=newArray(3,3,8,8);
c=newArray("c1","c2");
//answer should be g=(1,2,3,4,5,5,5,5,5,5,6,7,8,9,10, --x part
// 3,3,3,3,3,4,5,6,7,8,8,8,8,8,8) --y part
//f=slide(a,2,c);Array.print(f);
g=cmpltarray(X,Y);Array.print(g);
function cmpltarray(Tx,Ty){
for (i = 0; i < Tx.length-1; i++) {
if(Tx[i]==Tx[i+1] && Ty[i]!=Ty[i+1])
{
l=abs(Ty[i]-Ty[i+1])-1;tempy=newArray(l);tempx=newArray(l);
for (j = 0; j < l; j++) {
tempy[j]=Ty[i]+j+1;tempx[j]=Tx[i];
}
Tx=slide(Tx,(i+1),tempx);Ty=slide(Ty,(i+1),tempy);i=i+l;
}
if(Ty[i]==Ty[i+1] && Tx[i]!=Tx[i+1])
{
l=abs(Tx[i]-Tx[i+1])-1;tempy=newArray(l);tempx=newArray(l);
for (j = 0; j < l; j++) {
tempx[j]=Tx[i]+j+1;tempy[j]=Ty[i];
}
Tx=slide(Tx,(i+1),tempx);Ty=slide(Ty,(i+1),tempy);i=i+l;
}
}
return Array.concat(Tx,Ty);
}
function slide(array,n,data){
array=Array.concat(Array.slice(array,0,n),data,Array.slice(array,n,array.length));
return array;
}

Find middle element of a double linked list in constant time complexity

I am trying to find the middle element of a double linked list in constant time complexity .
I came across the following http://www.geeksforgeeks.org/design-a-stack-with-find-middle-operation/ solution.
But I don't understand how to use the middle pointer.
Can anyone please help me understand this or give me a better solution .
I've re-written this code in C++ for explanation purposes:
#include <iostream>
typedef class Node* PNode;
class Node{
public:
PNode next;
PNode prev;
int data;
Node(){
next = nullptr;
prev = nullptr;
data = 0;
}
};
class List{
private:
//Attributes
PNode head;
PNode mid;
int count;
//Methods
void UpdateMiddle( bool _add );
public:
//Constructors
List(){
head = nullptr;
mid = nullptr;
count = 0;
}
~List(){
while( head != nullptr ){
this->delmiddle();
std::cout << count << std::endl;
}
}
//Methods
void push( int _data );
void pop();
int findmiddle();
void delmiddle();
};
void List::UpdateMiddle( bool _add ){
if( count == 0 ){
mid = nullptr;
}
else if( count == 1 ){
mid = head;
}
else{
int remainder = count%2;
if(_add){
if( remainder == 0 ){
mid = mid->prev;
}
}
else{
if( remainder == 1 ){
mid = mid->next;
}
}
}
}
void List::push( int _data ){
PNode new_node = new Node();
new_node->data = _data;
new_node->prev = nullptr;
new_node->next = head;
if( head != nullptr ) head->prev = new_node;
head = new_node;
count++;
UpdateMiddle( true );
}
void List::pop(){
if( head != nullptr ){
PNode del_node = head;
head = head->next;
if( head != nullptr ) head->prev = nullptr;
delete del_node;
count--;
UpdateMiddle(false);
}
else if( count != 0 ){
std::cout << "ERROR";
return;
}
}
int List::findmiddle(){
if( count > 0 ) return mid->data;
else return -1;
}
void List::delmiddle(){
if( mid != nullptr ){
if( count == 1 || count == 2){
this->pop();
}
else{
PNode del_mid = mid;
int remainder = count%2;
if( remainder == 0 ){
mid = del_mid->next;
mid->prev = del_mid->prev;
del_mid->prev->next = mid;
delete del_mid;
count--;
}
else{
mid = del_mid->prev;
mid->next = del_mid->next;
del_mid->next->prev = mid;
delete del_mid;
count--;
}
}
}
}
The push and pop functions are self-explanatory, they add nodes on top of the stack and delete the node on the top. In this code, the function UpdateMiddle is in charge of managing the mid pointer whenever a node is added or deleted. Its parameter _add tells it whether a node has been added or deleted. This info is important when there is more than two nodes.
Note that when the UpdateMiddle is called within push or pop, the counter has already been increased or decreased respectively. Let's start with the base case, where there is 0 nodes. mid will simply be a nullptr. When there is one node, mid will be that one node.
Now let's take the list of numbers "5,4,3,2,1". Currently the mid is 3 and count, the amount of nodes, is 5 an odd number. Let's add a 6. It will now be "6,5,4,3,2,1" and count will now be 6 an even number. The mid should also now be 4, as it is the first in the middle, but it still hasn't updated. However, now if we add 7 it will be "7,6,5,4,3,2,1", the count will be 7, an odd number, but notice that the mid wont change, it should still be 4.
A pattern can be observed from this. When adding a node, and count changes from even to odd, the mid stays the same, but from odd to even mid changes position. More specifically, it moves one position to the left. That is basically what UpdateMiddle does. By checking whether count is currently odd or even after adding or deleting a node, it decides if mid should be repositioned or not. It is also important to tell whether a node is added or deleted because the logic works in reverse to adding when deleting. This is basically the logic that is being applied in the code you linked.
This algorith works because the position of mid should be correct at all times before adding or deleting, and function UpdateMiddle assumes that the only changes were the addition or deletion of a node, and that prior to this addition or deletion the position of mid was correct. However, we make sure of this by making the attributes and our function UpdateMiddle private, and making it modifiable through the public functions.
The trick is that you don't find it via a search, rather you constantly maintain it as a property of the list. In your link, they define a structure that contains the head node, the middle node, and the number of nodes; since the middle node is a property of the structure, you can return it by simply accessing it directly at any time. From there, the trick is to maintain it: so the push and pop functions have to adjust the middle node, which is also shown in the code.
More depth: maintaining the middle node: we know given the count that for an odd number of nodes (say 9), the middle node is "number of nodes divided by 2 rounded up," so 9/2 = 4.5 rounded up = the 5th node. So if you start with a list of 8 nodes, and add a node, the new count is 9, and you'll need to shift the middle node to the "next" node. That is what they are doing when they check if the new count is even.

Summation of Perceptron not working properly. Getting large summation

So I have a run method which summates the weights of the edges in the artificial neural network with the threshold values of the input nodes.
Sort of like this:
Now my test perceptron should produce a summation of -3, but I am getting a value of 1176!!! What is going on here?
Here is the code that I have written for my run() method, constructor, and my main method.
Constructor:
public class Perceptron {
//We want to create a variable which will represent the number of weighted edges
//in the 2-dimensional array.
protected int num_weighted_Edges;
//Inside this class we want to create a data field which is a
//2-D array of WeightedEdges. Since the weightedEdges will be in
//double data type, we will create a double type 2-dimensional
//array.
protected WeightedEdge[][] weightedEdges;
protected int[] weights;
//We set a double field named eta equal to 0.05.
protected double eta = 0.05;
//We initialize a constructor which only takes a parameter int n.
public Perceptron(int n){
//We want to create a new graph which will have n + 1 vertices
//, where we also want vertex 0 to act like the output node
//as in a neural network.
this.num_weighted_Edges = n;
weights = new int[num_weighted_Edges];
//First we need to verify that n is a positive real number
if (num_weighted_Edges < 0){
throw new RuntimeException("You cannot have a perceptron of negative value");
}
else {
//Test code for testing if this code works.
System.out.println("A perceptron of " + num_weighted_Edges + " input nodes, and 1 output node was created");
}
//Now we create a graph object with "n" number of vertices.
weightedEdges = new WeightedEdge[num_weighted_Edges + 1][num_weighted_Edges + 1];
//Create a for loop that will iterate the weightedEdges array.
//We want to create the weighted edges from vertex 1 and not vertex 0
//since vertex 0 will be the output node, so we set i = 1.
for (int i = 1; i < weightedEdges.length; i++){
for (int j = 0; j < weightedEdges[i].length; j++){
//This will create a weighted edge in between [1][0]...[2][0]...[3][0]
//The weighted edge will have a random value between -1 and 1 assigned to it.
weightedEdges[i][0] = new WeightedEdge(i, j, 1);
}
}
}
This is my run() method:
//This method will take the input nodes, do a quick verification check on it and
//sum up the weights using the simple threshold function described in class to return
//either a 1 or -1. 1 meaning fire, and -1 not firing.
public int run(int[] weights){
//So this method will act like the summation function. It will take the int parameters
//you put into the parameter field and multiply it times the input nodes in the
//weighted edge 2 d array.
//Setup a summation counter.
int sum = 0;
if (weights.length != num_weighted_Edges){
throw new RuntimeException("Array coming in has to equal the number of input nodes");
}
else {
//We iterate the weights array and use the sum counter to sum up weights.
for (int i = 0; i < weights.length; i++){
//Create a nested for loop which will iterate over the input nodes
for ( int j = 1; j < weightedEdges.length; j++){
for (int k = 0; k < weightedEdges[j].length; k++){
//This takes the weights and multiplies it times the value in the
//input nodes. The sum should equal greater than 0 or less than 0.
sum += (int) ((weightedEdges[j][0].getWeight()) * i);
//Here the plus equals sign takes the product of (weightedEdges[j][0] * i) and
//then adds it to the previous value.
}
}
}
}
System.out.println(sum);
//If the sum is greater than 0, we fire the neuron by returning 1.
if (sum > 0){
//System.out.println(1); test code
return 1;
}
//Else we don't fire and return -1.
else {
//System.out.println(-1); test code
return -1;
}
}
This is my main method:
//Main method which will stimulate the artificial neuron (perceptron, which is the
//simplest type of neuron in an artificial network).
public static void main(String[] args){
//Create a test perceptron with a user defined set number of nodes.
Perceptron perceptron = new Perceptron(7);
//Create a weight object that creates an edge between vertices 1 and 2
//with a weight of 1.5
WeightedEdge weight = new WeightedEdge(1, 2, 1.5);
//These methods work fine.
weight.getStart();
weight.getEnd();
weight.setWeight(2.0);
//Test to see if the run class works. (Previously was giving a null pointer, but
//fixed now)
int[] test_weight_Array = {-1, -1, -1, -1, -1, 1, 1};
//Tested and works to return output of 1 or -1. Also catches exceptions.
perceptron.run(test_weight_Array);
//Testing a 2-d array to see if the train method works.
int[][] test_train_Array = {{1}, {-1}, {1}, {1}, {1}, {1}, {1}, {1}};
//Works and catches exceptions.
perceptron.train(test_train_Array);
}
}
I think you should change
sum += (int) ((weightedEdges[j][0].getWeight()) * i);
to
sum += (int) ((weightedEdges[j][k].getWeight()) * i);

Deleting a node from the middle of a link list, function prototype is: int particle_remove(struct particle* p);

I have been working on this for like 10 hours.
int particle_remove(struct particle* p);
How do I find the head when I'm passing the location of the "node-to-be-deleted" to the function?
I know that:
prev->next = curr->next;
free(curr);
how do I find the location of the head to traverse down to (curr -1)?
This is what I have so far:
int particle_remove(struct particle *p){
struct particle *curr = p;
struct particle *prev = *head; /* should point to the head */
if (p != NULL){
while (prev != curr){
prev=curr->next;
}
prev->next = curr->next;
free(curr);
}
return 0;
}
I have been over this a million times and I can't think of how to get to the head node, without passing a parameter of the location of the head node into the function. Is it possible to do this with the current function "signature" or do I have to add a reference to the head?
OK I have figured it out by creating a new function that takes both the current node to be destroyed and a pointer to the head, as I don't believe that just using a function to the node to be deleted will work as there is no reference to the head. (Unless someone can prove me wrong, please do!)
I ended up with a prototype that looks like this: (for those that are looking for a hint)
int particle_remove(struct particle *p, struct particle **head);
The problem is: you have to change the head pointer if the pointer to be deleted (p) happens to be first in the list. Using a pointer-to-pointer (a pointer to the head pointer) is the easiest way:
int particle_remove(struct particle *p){
struct particle **pp; /* should point to the head */
for(pp = &head; *pp; pp = &(*pp)->next){
if (*pp != p) continue;
*pp = p->next;
free(p);
break;
}
return 0;
}
If head is not a gobal pointer, you indeed end up with a function where the pointer to head is passed as an argument:
int particle_remove(struct particle **pphead, struct particle *p){
for( ; *pphead; pphead = &(*pphead)->next){
if (*pphead != p) continue;
*pphead = p->next;
free(p);
break;
}
return 0;
}
BTW: the return value is nonsense. If there is no useful return for the function, it could just as well return void.
OK, so the way to solve this using the original function prototype is if you use:
if(p->next != NULL){
/* do something */
}
You are checking to see if the next node is to be deleted. This gives you access to the previous node and the next node (to be deleted).

Checking if removing an edge in a graph will result in the graph splitting

I have a graph structure where I am removing edges one by one until some conditions are met. My brain has totally stopped and i can't find an efficient way to detect if removing an edge will result in my graph splitting in two or more graphs.
The bruteforce solution would be to do an bfs until one can reach all the nodes from a random node, but that will take too much time with large graphs...
Any ideas?
Edit: After a bit of search it seems what I am trying to do is very similar to the fleury's algorithm, where I need to find if an edge is a "bridge" or not.
Edges that make a graph disconnected when removed are called 'bridges'. You can find them in O(|V|+|E|) with a single depth-first search over the whole graph. A related algorithm finds all 'articulation points' (nodes that, if removed, makes the graph disconnected) follows. Any edge between two articulation-points is a bridge (you can test that in a second pass over all edges).
//
// g: graph; v: current vertex id;
// r_p: parents (r/w); r_a: ascents (r/w); r_ap: art. points, bool array (r/w)
// n_v: bfs order-of-visit
//
void dfs_art_i(graph *g, int v, int *r_p, int *r_v, int *r_a, int *r_ap, int *n_v) {
int i;
r_v[v] = *n_v;
r_a[v] = *n_v;
(*n_v) ++;
// printf("entering %d (nv = %d)\n", v, *n_v);
for (i=0; i<g->vertices[v].n_edges; i++) {
int w = g->vertices[v].edges[i].target;
// printf("\t evaluating %d->%d: ", v, w);
if (r_v[w] == -1) {
// printf("...\n");
// This is the first time we find this vertex
r_p[w] = v;
dfs_art_i(g, w, r_p, r_v, r_a, r_ap, n_v);
// printf("\n\t ... back in %d->%d", v, w);
if (r_a[w] >= r_v[v]) {
// printf(" - a[%d] %d >= v[%d] %d", w, r_a[w], v, r_v[v]);
// Articulation point found
r_ap[i] = 1;
}
if (r_a[w] < r_a[v]) {
// printf(" - a[%d] %d < a[%d] %d", w, r_a[w], v, r_a[v]);
r_a[v] = r_a[w];
}
// printf("\n");
}
else {
// printf("back");
// We have already found this vertex before
if (r_v[w] < r_a[v]) {
// printf(" - updating ascent to %d", r_v[w]);
r_a[v] = r_v[w];
}
// printf("\n");
}
}
}
int dfs_art(graph *g, int root, int *r_p, int *r_v, int *r_a, int *r_ap) {
int i, n_visited = 0, n_root_children = 0;
for (i=0; i<g->n_vertices; i++) {
r_p[i] = r_v[i] = r_a[i] = -1;
r_ap[i] = 0;
}
dfs_art_i(g, root, r_p, r_v, r_a, r_ap, &n_visitados);
// the root can only be an AP if it has more than 1 child
for (i=0; i<g->n_vertices; i++) {
if (r_p[i] == root) {
n_root_children ++;
}
}
r_ap[root] = n_root_children > 1 ? 1 : 0;
return 1;
}
If you remove the link between vertices A and B, can't you just check that you can still reach A from B after the edge removal? That's a little better than getting to all nodes from a random node.
How do you choose the edges to be removed?
Can you tell more about your problem domain?
Just how large Is your graph? maybe BFS is just fine!
After you wrote that you are trying to find out whether an edge is a bridge or not, I suggest
you remove edges in decreasing order of their betweenness measure.
Essentially, betweenness is a measure of an edges (or vertices) centrality in a graph.
Edges with higher value of betweenness have greater potential of being a bridge in a graph.
Look it up on the web, the algorithm is called 'Girvan-Newman algorithm'.

Resources