sparse matrix using linked list C++ - c++

I'm coding the program that using linked list to store a sparse matrix. First I create a class "Node" contains the index of entry, value of entry and two pointers to next row and next column. Second I find on Google that I need to create the class Matrix like this code below but I don't understand the meaning of Node **rowList and node** columnList. Why they use a pointer to a pointer there and how could I implement a matrix from that? Thank you so much.
class Node
{
public:
int iValue, jValue;
float value;
Node *rowPtr;
Node *colPtr;
};
class Matrix
{
Node **rowList; // rowList is the pointer to the array of rows
Node **columnList; // columnList is the pointer to the array of columns
int rows, cols; // number of rows and columns
}

It appears to be exactly what the comment says. They are arrays. Presumably rowList will be an array of rows elements, and columnList will be an array of cols elements. The reason it's a Node** is that each item in the array is a Node*. A pointer to an array always has an extra level of indirection (an extra *). That means when you index a single element out of that array you get a value of type Node* again.
The arrays are created like this:
rowList = new Node* [rows];
columnList = new Node* [cols];
// Don't forget to initialise the values to NULL! Here's the dull way:
for( int i = 0; i < rows; i++ ) rowList[i] = NULL;
for( int i = 0; i < cols; i++ ) columnList[i] = NULL;
When you need to delete them (in the destructor for Matrix):
delete [] rowList;
delete [] colList;
As for your question on how to implement your matrix from that, that's really up to you. Presumably when you create a node at position (i, j), you append that node to each of rowList and columnList. ie:
Node * node = new Node(i, j, 123.0);
rowList[i] = node;
columnList[j] = node;
But it's not that simple, because the node obviously must be linked into both a row and column list. At the very basic level, and using the structures you've provided, here's one way:
// Inserts newNode at the head of the list and modifies the head pointer.
void insert_row( Node* & r, Node *newNode )
{
newNode->rowPtr = r;
if( r != NULL ) r->rowPtr = newNode;
r = newNode;
}
// Similarly with insert_col()...
Now using the above with my original example:
Node * node = new Node(i, j, 123.0);
insert_row( rowList[i], node );
insert_col( columnList[j], node );
For ordered insert
Since you have code already, I will offer my take on it. But you still need to do some work yourself.
I just try to understand the concept but it's so confusing for me.
Let's just clean things up to begin with. It's a class, and you're using C++ so please use your C++ knowledge:
class Node
{
public:
Node( int i, int j, int val );
void InsertRowAfter( Node* node );
void InsertColAfter( Node* node );
int iValue, jValue; // Row and column index, 1-based
float value; // Element value
Node *rowPtr; // Next element in this row (sorted by jValue)
Node *colPtr; // Next element in this column (sorted by iValue)
};
Node::Node( int i, int j, int val )
: iValue(i)
, jValue(j)
, value(val)
, rowPtr(NULL)
, colPtr(NULL)
{}
// Inserts the given node to follow this node in the row list
void Node::InsertRowAfter( Node* node )
{
// [go on, you do it]
}
// Inserts the given node to follow this node in the column list
void Node::InsertColAfter( Node* node );
{
// [go on, you do it]
}
So, now you need to implement the Matrix::inputData function... Essentially you do what your friend was trying to do, but without the errors and memory leaks. That means you start like this:
// Use 'horz' and 'vert' to search through the row and column lists. If a
// node needs to be created, it will be stored in 'node'.
Node *horz = rowList[iValue - 1];
Node *vert = columnList[jValue - 1];
Node *node;
// If there is no row list or smallest jValue, insert at the head.
// Otherwise, search for an insert point.
if( !horz || horz->jValue > jValue )
{
// [go on, you do it]
}
else
{
// Move 'horz' pointer to position at which we will append a node.
Node *next = horz->rowPtr;
while( next && next->jValue <= jValue ) {
horz = next;
next = next->rowPtr;
}
// If replacing an existing value, there's nothing else to do.
if( horz->jValue == jValue ) {
horz->value = value;
return;
}
// Otherwise append a new node.
// [go on, you do it]
}
Now, you finish the function off, and don't forget to do the column indexing...

Related

Adding a node to a complete tree

I'm trying to make complete tree from scratch in C++:
1st node = root
2nd node = root->left
3rd node = root->right
4th node = root->left->left
5th node = root->left->right
6th node = root->right->left
7th node = root->right->right
where the tree would look something like this:
NODE
/ \
NODE NODE
/ \ / \
NODE NODE NODE NODE
/
NEXT NODE HERE
How would I go about detecting where the next node would go so that I can just use one function to add new nodes? For instance, the 8th node would be placed at root->left->left->left
The goal is to fit 100 nodes into the tree with a simple for loop with insert(Node *newnode) in it rather than doing one at a time. It would turn into something ugly like:
100th node = root->right->left->left->right->left->left
Use a queue data structure to accomplish building a complete binary tree. STL provides std::queue.
Example code, where the function would be used in a loop as you request. I assume that the queue is already created (i.e. memory is allocated for it):
// Pass double pointer for root, to preserve changes
void insert(struct node **root, int data, std::queue<node*>& q)
{
// New 'data' node
struct node *tmp = createNode(data);
// Empty tree, initialize it with 'tmp'
if (!*root)
*root = tmp;
else
{
// Get the front node of the queue.
struct node* front = q.front();
// If the left child of this front node doesn’t exist, set the
// left child as the new node.
if (!front->left)
front->left = tmp;
// If the right child of this front node doesn’t exist, set the
// right child as the new node.
else if (!front->right)
front->right = tmp;
// If the front node has both the left child and right child, pop it.
if (front && front->left && front->right)
q.pop();
}
// Enqueue() the new node for later insertions
q.push(tmp);
}
Suppose root is node#1, root's children are node#2 and node#3, and so on. Then the path to node#k can be found with the following algorithm:
Represent k as a binary value, k = { k_{n-1}, ..., k_0 }, where each k_i is 1 bit, i = {n-1} ... 0.
It takes n-1 steps to move from root to node#k, directed by the values of k_{n-2}, ..., k_0, where
if k_i = 0 then go left
if k_i = 1 then go right
For example, to insert node#11 (binary 1011) in a complete tree, you would insert it as root->left->right->right (as directed by 011 of the binary 1011).
Using the algorithm above, it should be straightforward to write a function that, given any k, insert node#k in a complete tree to the right location. The nodes don't even need to be inserted in-order as long as new nodes are detected created properly (i.e. as the correct left or right children, respectively).
Assuming tree is always complete we may use next recursion. It does not gives best perfomance, but it is easy to understand
Node* root;
Node*& getPtr(int index){
if(index==0){
return root;
}
if(index%2==1){
return (getPtr( (index-1)/2))->left;
}
else{
return (getPtr( (index-2)/2))->right;
}
}
and then you use it like
for(int i = 0; i<100; ++i){
getPtr(i) = new Node( generatevalue(i) );
}
private Node addRecursive(*Node current, int value) {
if (current == null) {
return new Node(value);
}
if (value < current.value) {
current->left = addRecursive(current->left, value);
} else if (value > current->value) {
current->right = addRecursive(current->right, value);
} else {
// value already exists
return current;
}
return current;
}
I do not know that if your Nodes has got a value instance but:
With this code you can have a sorted binary tree by starting from the root.
if the new node’s value is lower than the current node’s, we go to the left child. If the new node’s value is greater than the current node’s, we go to the right child. When the current node is null, we’ve reached a leaf node and we can insert the new node in that position.

Get smallest value from a linked list?

I am currently writing a piece of code which loops through a linked list and retrieves the smallest, but is not working. Instead it seems to be returning the last value I enter into the list...
(list is the head being passed from main)
int i = 0;
Stock *node = list;
int tempSmallest = (list + 0)->itemStock;
while (node!=NULL)
{
if ((list+i)->itemStock < tempSmallest)
{
tempSmallest = node->itemStock;
node = node->nodeptr;
}
i++;
}
return list;
Thanks for any advice!
You are dereferencing (list+i) and incrementing i with every visited node for some reason. I don't know why you're doing this, but it's wrong. You basically traverse the linked list and also conceptually traverse an array (which doesn't exist at all). This is undefined behavior and cannot give meaningful results.
You must dereferece the currently valid node, not an array element that is a few indices after it somewhere in RAM, and advance by the list's next node pointer (I assume this is called nodeptr in your code?).
Something like...
Stock *node = list; // hopefully not NULL since I don't check in the next line
int smallest = node->itemStock;
while(node && node = node->nodeptr)
smallest = std::min(smallest, node->itemStock);
return smallest;
struct stock{
stock *next;
...
};
this will be the struct of your nodes.
then when you initialize them, you should refer the next pointer of the last node added, to the node you're adding currently.
then the code will be like this:
stock *node = head; // the head you passed from main
int min = node->price;
for(;node;node=node->next)
{
if(node->price < min)
min = node->price;
if(!node->next)
break();
}
return min;

inserting node function confusing

I'm trying to understand this function to insert an element into a linked list of sorted integers in ascending order, however, there are parts of the code that are confusing me...
Node* insert (int x, Node *p) {
if (p==nullptr)
return cons(x,nullptr); //inserts the new node at front of list,before node with nullptr?
if (x < = p-> val)
return cons(x,p); //this also inserts node at front of the list?
//now the rest of the function is where I get confused...
Node *prev=p; //so this is not allocating new memory, so what exactly does it mean?
Node * after=prev->next;
//prev->next is pointing at whatever after is pointing to but after has no address?
while (after!=nullptr && x > after->val) { //whats going on here?
prev=after;
after=after-> next;
}
prev->next=cons(x,after);
return p;
}
Node* insert (int x, Node *p) {
if (p==nullptr)
return cons(x,nullptr);
//inserts the new node at front of list,before node with nullptr?
if (x < = p-> val)
return cons(x,p); //this also inserts node at front of the list?
The code above takes care of inserting the new element at the beginning of the linked list. There are two instances for this to happen:
if the head, which is p in this case, is NULL.
if the element that p is pointing to has a value greater than the current element to be inserted.
Now going forward...
//now the rest of the function is where I get confused...
Node *prev=p;
//so this is not allocating new memory, so what exactly does it mean?
This is just like a temporary pointer which can be used to traverse the linked list. So you store the head 'p' in the prev pointer.
Node * after=prev->next;
//prev->next is pointing at whatever
//after is pointing to but after has no address?
This is a pointer that would store the next element of head.
while (after!=nullptr && x > after->val) { //whats going on here?
prev=after;
after=after-> next;
}
prev->next=cons(x,after);
return p;
}
Here, this looks a little buggy. You might want to do something like this, instead:
While(prev->data >= inputdata && (after->data < inputdata || after == NULL)
{
//insert your inputdata here because it is greater than the previous but less than after
// or after is NULL.
}
I hope this clarifies your confusion. Let me know if you have any questions.

BFS implementation

i was recently solving a bfs problem where each node is a different arrangement of elements of an array. but i was unable to come up with a suitable data structure to keep track of the visited nodes in the expanded tree. generally the nodes are different strings so we can just use a map to mark a node as visited but what DS should i use in the above case?
Consider the following pseudocode:
type Node; // information pertaining to a node
type Path; // an ordered list of nodes
type Area; // an area containing linked neighboring nodes
type Queue; // a FIFO queue structure
function Traverse(Area a, Node start, Node end) returns Path:
Queue q;
Node n;
// traverse backwards, from finish to start
q.push(end); // add initial node to queue
end.parent = end; // set first node's parent to itself
while (not q.empty()):
n = q.pop(); // remove first element
if (n == start) // if element is the final element, we're done
break;
for (Node neighbor in a.neighbors(n)): // for each neighboring node
if (neighbor.parent != Null): // if already visited, skip
continue;
neighbor.parent = n; // otherwise, visit
q.push(neighbor); // then add to queue
Path p; // prepare to build path from visited list
for (Node previous = Null, current = n;
previous != current;
previous = current, current = current.parent):
p.add(current); // for each node from start to end, add node to p
// Note that the first node's parent is itself
// thus dissatisfying the loop condition
return p;
The "visited list" is stored as the node's parent. Coding this to C++, you would probably handle most of the nodes as references or pointers since this pseudocode relies on referential behavior.
You start with an Area, which is a field of Nodes. The area knows where each node is in relation to the others. You start at one specific Node, the "start" node, and push it into a queue.
Traversing the area is as simple as getting the list of neighboring nodes from the Area, skipping them if they're already visited, and setting their parent and adding them to the queue otherwise. Traversal ends when a node removed from the queue equals the destination node. You could speed up the algorithm a little by doing this check during the neighbor loop, when the node is initially encountered.
NOTE: You do not need to generate every possible node within the area before beginning the traversal, the Area requires only that once it has created a node, it keeps track of it. This might help your situation where it appears you use permutations of strings or arrays: you could push the starting and ending nodes into the Area, and it could generate and cache neighbor nodes on the fly. You might store them as vectors, which can be compared for equality based on their order and contents with the == operator. See this example.
The traversal goes backwards rather than forwards because it makes rebuilding the path easier (rather than ending up at the end node, with each parent the node before it, you end up at the start node, with each parent the node after it)
Data Structure Summary
Node would need to keep track of enough information for Area to identify it uniquely (via an array index or a name or something), as well as a parent node. The parent nodes should be set to NULL before the traversal to avoid weird behavior, since traversal will ignore any node with its parent set. This keeps track of the visited state too: visited is equivalent to (parent != NULL). Doing it this way also keeps you from having to keep track of the entire path in the queue, which would be very computationally intensive.
Area needs to maintain a list of Node, and needs a neighbor map, or a mapping of which nodes neighbor which other nodes. It's possible that this mapping could be generated on the fly with a function rather than being looked up from a table or some more typical approach. It should be able to provide the neighbors of a node to a caller. It might help to have a helper method that clears the parents of every node as well.
Path is basically a list type, containing an ordered list of nodes.
Queue is whatever FIFO queue is available. You could do it with a linked list.
I like how the syntax highlighting worked on my Wuggythovasp++.
At least as a start, you could try using/implementing something like Java's Arrays.toString() and using a map. Each arrangement would result in a different string, and thus it'll at least get somewhere.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author VAISAKH N
*/
public class BFSME {
public static String path = "";
public static String add = "";
public static void findrec(String temp, String end, String[][] m, int j) {
if (temp.equals(m[j][1])) {
add = m[j][0] + temp + end + "/";
end = temp + end;
System.out.println(end);
path = path + add;
temp = "" + add.charAt(0);
System.out.println("Temp" + temp);
for (int k = 0; k < m.length; k++) {
findrec(temp, end, m, k);
}
}
}
public static void main(String[] args) {
String[][] data = new String[][]{{"a", "b"}, {"b", "c"}, {"b", "d"}, {"a", "d"}};
String[][] m = new String[data.length][2];
for (int i = 0; i < data.length; i++) {
String temp = data[i][0];
String end = data[i][1];
m[i][0] = temp;
m[i][1] = end;
path = path + temp + end + "/";
for (int j = 0; j < m.length; j++) {
findrec(temp, end, m, j);
}
}
System.out.println(path);
}
}
Just for the purpose of understanding, i have provided my sample code here (its in C#)
private void Breadth_First_Travers(Node node)
{
// First Initialize a queue -
// it's retrieval mechanism works as FIFO - (First in First Out)
Queue<Node> myQueue = new Queue<Node>();
// Add the root node of your graph into the Queue
myQueue.Enqueue(node);
// Now iterate through the queue till it is empty
while (myQueue.Count != 0)
{
// now, retrieve the first element from the queue
Node item = myQueue.Dequeue();
Console.WriteLine("item is " + item.data);
// Check if it has any left child
if (item.left != null)
{
// If left child found - Insert/Enqueue into the Queue
myQueue.Enqueue(item.left);
}
// Check if it has right child
if (item.right != null)
{
// If right child found Insert/Enqueue into the Queue
myQueue.Enqueue(item.right);
}
// repeat the process till the Queue is empty
}
}
Here sample code is give with reference of http://en.wikipedia.org/wiki/Binary_tree
as tree is a type of graph it self.
Here is BFS implementation using C++ STL(adjacency lists) for Graph. Here three Array and a Queue is used for complete implementation.
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
//Adding node pair of a Edge in Undirected Graph
void addEdge( vector<int> adj[], int u, int v){
adj[u].push_back(v); // 1st push_back
adj[v].push_back(u); //2nd push_back
//for Directed Graph use only one push_back i.e., 1st push_back() rest is same
}
//Traversing through Graph from Node 0 in Adjacency lists way
void showGraph( vector<int>adj[], int size){
cout<<"Graph:\n";
for(int i=0; i<size ; i++){
cout<<i;
for( vector<int>::iterator itr= adj[i].begin() ; itr!=adj[i].end(); itr++){
cout<<" -> "<<*itr;
}
cout<<endl;
}
}
//Prints Array elements
void showArray(int A[]){
for(int i=0; i< 6; i++){
cout<<A[i]<<" ";
}
}
void BFS( vector<int>adj[], int sNode, int N){
// Initialization
list<int>queue; //Queue declaration
int color[N]; //1:White, 2:Grey, 3:Black
int parentNode[N]; //Stores the Parent node of that node while traversing, so that you can reach to parent from child using this
int distLevel[N]; //stores the no. of edges required to reach the node,gives the length of path
//Initialization
for(int i=0; i<N; i++){
color[i] = 1; //Setting all nodes as white(1) unvisited
parentNode[i] = -1; //setting parent node as null(-1)
distLevel[i] = 0; //initializing dist as 0
}
color[sNode] = 2; //since start node is visited 1st so its color is grey(2)
parentNode[sNode] = -1; //parent node of start node is null(-1)
distLevel[sNode] = 0; //distance is 0 since its a start node
queue.push_back(sNode); //pushing start node(sNode) is queue
// Loops runs till Queue is not empty if queue is empty all nodes are visited
while( !queue.empty()){
int v = queue.front(); //storing queue's front(Node) to v
// queue.pop_front();//Dequeue poping element from queue
//Visiting all nodes connected with v-node in adjacency list
for(int i=0; i<adj[v].size() ;i++){
if( color[ adj[v][i] ] == 1){// if node is not visited, color[node]==1 which is white
queue.push_back(adj[v][i]); //pushing that node to queue
color[adj[v][i]]=2; //setting as grey(2)
parentNode[ adj[v][i] ] = v; //parent node is stored distLevel[ adj[v][i] ] = distLevel[v]+1; //level(dist) is incremented y from dist(parentNode)
}
}//end of for
color[v]=3;
queue.pop_front();//Dequeue
}
printf("\nColor: \n");showArray(color);
printf("\nDistLevel:\n");showArray(distLevel);
printf("\nParentNode:\n");showArray(parentNode);
}
int main(){
int N,E,u,v;//no of nodes, No of Edges, Node pair for edge
cout<<"Enter no of nodes"<<endl;
cin>>N;
vector<int> adj[N]; //vector adjacency lists
cout<<"No. of edges"<<endl;
cin>>E;
cout<<"Enter the node pair for edges\n";
for( int i=0; i<E;i++){
cin>>u>>v;
addEdge(adj, u, v); //invoking addEdge function
}
showGraph(adj,N); //Printing Graph in Adjacency list format
BFS(adj,0,N); /invoking BFS Traversal
}

Deep Copy Linked List - O(n)

I'm trying to deep copy a linked list . I need an algorithm that executes in Linear Time O(n). This is what i have for now , but i'm not able to figure out what's going wrong with it. My application crashes and i'm suspecting a memory leak that i've not been able to figure out yet. This is what i have right now
struct node {
struct node *next;
struct node *ref;
};
struct node *copy(struct node *root) {
struct node *i, *j, *new_root = NULL;
for (i = root, j = NULL; i; j = i, i = i->next) {
struct node *new_node;
if (!new_node)
{
abort();
}
if (j)
{
j->next = new_node;
}
else
{
new_root = new_node;
}
new_node->ref = i->ref;
i->ref = new_node;
}
if (j)
{
j->next = NULL;
}
for (i = root, j = new_root; i; i = i->next, j = j->next)
j->ref =i->next->ref;
return new_root;
}
Can anyone point out where i'm going wrong with this ??
This piece alone:
struct node *new_node;
if (!new_node)
{
abort();
}
Seems good for a random abort() happening. new_node is not assigned and will contain a random value. The !new_node expression could already be fatal (on some systems).
As a general hint, you should only require 1 for-loop. Some code upfront to establish the new_root.
But atruly deep copy would also require cloning whatever ref is pointing to. It seems to me the second loop assigns something from the original into the copy. But I'm not sure, what is ref ?
One thing I immediately noticed was that you never allocate space for new_node. Since auto variables are not guaranteed to be initialized, new_node will be set to whatever value was in that memory before. You should probably start with something like:
struct node *new_node = (new_node *) malloc(sizeof(struct node));
in C, or if you're using C++:
node* new_node = new node;
Copying the list is simple enough to do. However, the requirement that the ref pointers point to the same nodes in the new list relative to the source list is going to be difficult to do in any sort of efficient manner. First, you need some way to identify which node relative to the source list they point to. You could put some kind of identifier in each node, say an int which is set to 0 in the first node, 1 in the second, etc. Then after you've copied the list you could make another pass over the list to set up the ref pointers. The problem with this approach (other that adding another variable to each node) is that it will make the time complexity of the algorithm jump from O(n) to O(n^2).
This is possible, but it takes some work. I'll assume C++, and omit the struct keyword in struct node.
You will need to do some bookkeeping to keep track of the "ref" pointers. Here, I'm converting them to numerical indices into the original list and then back to pointers into the new list.
node *copy_list(node const *head)
{
// maps "ref" pointers in old list to indices
std::map<node const *, size_t> ptr_index;
// maps indices into new list to pointers
std::map<size_t, node *> index_ptr;
size_t length = 0;
node *curn; // ptr into new list
node const *curo; // ptr into old list
node *copy = NULL;
for (curo = head; curo != NULL; curo = curo->next) {
ptr_index[curo] = length;
length++;
// construct copy, disregarding ref for now
curn = new node;
curn->next = copy;
copy = curn;
}
curn = copy;
for (size_t i=0; i < length; i++, curn = curn->next)
index_ptr[i] = curn;
// set ref pointers in copy
for (curo = head, curn = copy; curo != NULL; ) {
curn->ref = index_ptr[ptr_index[curo->ref]];
curo = curo->next;
curn = curn->next;
}
return copy;
}
This algorithm runs in O(n lg n) because it stores all n list elements in an std::map, which has O(lg n) insert and retrieval complexity. It can be made linear by using a hash table instead.
NOTE: not tested, may contain bugs.