Graph Representation using Linked-List - c++

Im having some trouble trying to figure out how to get the pointers right when adding edges to a certain paired vertex.
Below is a short idea about how the linked list should look like after Vertexs and Nodes are done being Inputed.
How can i keep order on the neighborList as well? Should there be another condition if there is already a vertex edge in that current vertex?
Heres the Structured Class im trying to build:
class graph{
private:
typedef struct node{
char vertex;
node * nodeListPtr;
node * neighborPtr;
}* nodePtr;
nodePtr head;
nodePtr curr;
public:
graph();
~graph();
void AddNode(char AddData);
void AddEdge(char V, char E);
void printList();
};
graph::graph(){
head = NULL;
curr = NULL;
}
// Adds a node to a linked list
void graph::AddNode(char AddData){
nodePtr n = new node;
n->nodeListPtr = NULL;
n->vertex = AddData;
if(head != NULL){
curr = head;
while(curr->nodeListPtr != NULL){
curr = curr->nodeListPtr;
}
curr->nodeListPtr = n;
}
else{
head = n;
}
}
// takes 2 Parameters (V is pointing to E)
// I want to set it up where the neighborptr starts a double linked List basically
void graph::AddEdge(char V, char E){
// New Node with data
nodePtr n = new node;
n->neighborPtr = NULL;
n->vertex = E;
// go to the first node in the nodeList and go through till you reach the Vertex V
curr = head;
while(curr->vertex != V){
curr = curr->nodeListPtr;
}
//Once the Vertex V is found in the linked list add the node to the neighborPtr.
curr->neighborPtr = n;
}

One problem you currently have is that each node can only have one "edge" node. In your illustration, nodes A, C, and D are all possible, but node B is not without doing things a little differently.
The problem happens here:
curr->neighborPtr = n;
Every time you call AddEdge() to the same vertex, it will simply overwrite that vertex's neighborPtr. You make no effort to traverse the neighborPtrs until you find a null pointer.
Consider adding another while loop for adding edges recursively:
while (curr->neighborPtr != null)
curr = curr->neighborPtr;
curr->neighborPtr = n;
Note that this is not the only issue in your code; you have a few places where you should be guarding against null pointers and are not. For example: in AddEdge(), what happens if the vertex V cannot be found? You are acting under the assumption that it has already been created. If it hasn't, you will end up with some null pointer errors. Keep this in mind if you are trying to make code that is robust in addition to being functional.

Related

Why am I getting this runtime error: member access within null pointer of type 'Solution::node' (solution.cpp)

I was solving a question on leetcode 1409. Queries on a Permutation With Key, but I am getting this runtime error I don't know why. I am unable to debug this error.
Problem Statement:Given the array queries of positive integers between 1 and m, you have to process all queries[i] (from i=0 to i=queries.length-1) according to the following rules:
In the beginning, you have the permutation P=[1,2,3,...,m].
For the current i, find the position of queries[i] in the permutation P (indexing from 0) and then move this at the beginning of the permutation P. Notice that the position of queries[i] in P is the result for queries[i].
Return an array containing the result for the given queries.
My approach: I created a linkedlist to store the integers form 1 to m.
Then according to each query, I pass it to a function getpos() which returns the position of that query in the list and then updates it as per the directions given in problem statement.
This return value is then added to a result vector which is supposed to be the final answer after all queries are processed.
I have added comments to better understand my code
class Solution {
public:
struct node {
int data;
node* next = NULL;
};
node* addnode(node* head, int data) {
if(head == NULL) {
head = new node;
head->data = data;
}
else {
node* temp = head;
while(temp->next != NULL) { temp = temp->next; }
temp->data = data;
}
return head;
}
int getpos(node** head, int data) { //To get position of given query
int count = 0;
node* temp = *head;
node* prev;
while(temp->data != data) { //runtime error:member access within null pointer of type 'Solution::node' (solution.cpp); SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior prog_joined.cpp:32:21
prev = temp;
temp = temp->next;
count++;
}
prev->next = temp->next; //searched node deleted
temp->next = *head; //add the searched node to beginning of the list
*head = temp; //udapate head
return count; //we have position stored in count;
}
vector<int> processQueries(vector<int>& queries, int m) {
node* head = NULL;
for(int i=0;i<m;i++) { head = addnode(head,i+1); }
int n = queries.size();
vector<int> result;
for(int i=0;i<n;i++) { result.push_back(getpos(&head,queries[i])); }
return result;
}
};
Please debug and explain the cause of the error. I face many runtime errors which I fail to debug.
Your add_node function is bugged. Just take a deep breath and look at the code. add_node should allocate a node using new every time it is called. Ask yourself how many times and under what circumstances your version allocates a new node?
I'm sure you can see that your code only allocates a new node when head equals NULL, therefore it must be bugged.
Incidentally if you wanted a linked list why didn't you use std::list? You would have avoided the mistake you made.

LinkedList Node Insertion

I know this is seriously basic stuff, but I for the life of me can't seem to understand how I would go about doing this:
Q: Given the following struct definition for a Node:
struct Node
{
int value;
Node* next;
};
And given the declaration:
Node* head;
The following Linked List of Nodes has been constructed, with the head pointer assigned to the Node object 3:
head ----> 3 ----> 9 ----> 34 ----> -5 ----> NULL
Write a single C++ statement that will store the value 34 in the 3rd Node in the variable result:
int result =
Where would be a good place to start? Is this asking me to add an element to the list, or is it adding an entirely new node to the list? So confused!!
head->next->next will point to the third node in the linked list.
So,
int result = head->next->next->data;
will store the value in the third node in the list.
The question is asking you to read the third node and store it's value in result.
Linked lists employ a chain concept, where each chain-link along the entire length of the chain is connected at the front of each link.
People represent this in various ways. One example is:
struct Node {
int value;
Node* front;
};
Or:
struct Node {
int value;
Node* next;
};
When you establish the head of a linked list, you are creating the first node in the chain:
Node* head;
head = NULL; // this is an empty linked list
Whenever you want to add a node (or "link") to the chain, you pass along the new node to "Head", which keeps track of the chain:
void newNode(int value, Node* head)
{
Node *node;
node = new Node*; // or (Node*)malloc(sizeof(Node));
node->value = value;
node->next = head;
head = node;
}
Using this concept, you can add any number of links to your chain. Thomas and warun have good examples of this.
Hope this helps.
example for a loop.
Node* temp = head;
int number = 300; //the place you are looking for
if(temp)
{
int i;
for(i = 0 ; i< number && temp->next != nullptr ;i++)
{
temp = temp->next;
}
if(i == 300)
{
//found you value;
result = temp->value;
}
}

Storing Linked lists as a index in an Array C++

Overview: Im currently attempting to write a code that will take a AOV Network graph and put it into a Linked List. I am how ever having trouble whats the best way to go about this. I understand on paper how graphs can be represented in the linked list form.
Here is the graph im going off of:
My Thought process/Pusdo code would be as follows:
Create a Linked-List class that just adds the nodes and prints them out for the methods.
Then for each edge access the index of an array and go to that Linked list.
So then my array would have [s,a,d,g,b,e,h,c,f,i,t] where each letter would represent the >Linked list of that vertex. So if i would like to call the S vertex i would have to call the >0 element of the array and that would point to s Linked-List. Is there a easy implementation >of this in C++?
Here is my Linked-List Class right now:
class List{
private:
typedef struct node{
char vertex;
node* next;
}* nodePtr;
nodePtr head;
nodePtr curr;
nodePtr temp;
public:
List();
void AddNode(char AddData);
void printList();
};
List::List(){
head = NULL;
curr = NULL;
temp = NULL;
}
void List::AddNode(char AddData){
nodePtr n = new node;
n->next = NULL;
n->vertex = AddData;
if(head != NULL){
curr = head;
while(curr->next != NULL){
curr = curr->next;
}
curr->next = n;
}
else{
head = n;
}
}
void List::printList(){
curr = head;
while(curr != NULL){
cout << curr->vertex << endl;
curr = curr->next;
}
}
Any help would be much appreciated.
EDIT:
Can Using a Double Linked List like this work?
There is a data structure named Adjacent Table to store graph in a linkedlist structure
the element in AT is like
struct ATEle {
char name;
ATEle * neighborPointer;
ATEle * nodelistPointer;
}
the nodes in the graph are organized in a linkedlist, and each node is also the head of a linked list of all its neighbors
e.g. we have a graph of 4 nodes, A, B, C, D, and A connects with B, C, D connects with A, B with C, D, in the adjancent table it looks like :
A -> B -> C
|
B -> C ->D
|
C
|
D -> A
You have a graph problem, not a list problem. Use the graph metaphors of "node" and "edge" instead of "list."

C++ Linked list implementation crashing

I am trying to implement a linked list for a data structures class and I am having some difficulty with the searching portion of the algorithm.
Below is the offending code, which I have tried to implement following the pseudo-code in the MIT introduction to algorithms text:
//
// Method searches and retrieves a specified node from the list
//
Node* List::getNode(unsigned position)
{
Node* current = m_listHead;
for(unsigned i = m_listSize-1; (current != 0) && (i != position); --i)
current = current->next;
return current;
}
The head at this point in the program is the 4th node, which contains the value of int 5. the problem appears to be in the body of the for-loop, where the pointer to the node object is assigned to the next node. But this is going beyond the head of the node, so it is essentially pointing at some random location in memory (this makes sense).
Shouldn't the algorithm be moving to the previous Node instead of the next Node in this case? Below is the pseudo-code:
LIST-SEARCH(L, k)
x <- head
while x != NIL and key != k
do x <- next[x]
return x
Also, here is the header file for my Linked list implementation. I haven't tried to implement it in Template form yet just to keep things simple:
#ifndef linkList_H
#define linkList_h
//
// Create an object to represent a Node in the linked list object
// (For now, the objects to be put in the list will be integers)
//
struct Node
{
// nodes of list will be integers
int number;
// pointer to the next node in the linked list
Node* next;
};
//
// Create an object to keep track of all parts in the list
//
class List
{
public:
// Contstructor intializes all member data
List() : m_listSize(0), m_listHead(0) {}
// methods to return size of list and list head
Node* getListHead() const { return m_listHead; }
unsigned getListSize() const { return m_listSize; }
// method for adding a new node to the linked list,
// retrieving and deleting a specified node in the list
void addNode(Node* newNode);
Node* getNode(unsigned position);
private:
// member data consists of an unsigned integer representing
// the list size and a pointer to a Node object representing head
Node* m_listHead;
unsigned m_listSize;
};
#endif
Implementation of addNode method:
//
// Method adds a new node to the linked list
//
void List::addNode(Node* newNode)
{
Node* theNode = new Node;
theNode = newNode;
theNode->next;
m_listHead = theNode;
++m_listSize;
}
Try this to construct the list:
void List::addNode(int number)
{
newNode = new Node;
newNode -> number = number;
newNode -> next = m_listHead ;
m_listHead = newNode;
++m_listSize;
}
It will add nodes to the head. Perhaps you may wish to store the pointer to the tail and insert the nodes there.
Unfortunately your code doesn't resemble the pseudo code you supply.
The pseudo-code is for searching a linked-list for a key, not a position.
The pseudo code reads as:
Assign head to (node) x.
while x isn't null and the key inside the current node (x) doesn't match k
assign x->next to x
return x
The returned value is either a pointer to the node that contains k or null
If you're trying to find the node at a given position your loop would be (note this is assuming you're going to use a zero-based index for accessing the list):
Assign head to (node) x
assign 0 to (int) pos
while x isn't null and pos not equal to given position
assign x->next to x
increment pos
return x
The result will either be a pointer to the node at the given position or null (if you hit the end of the list first)
Edit: Your code is very close to the latter if that's what you're trying to do ... can you see the difference?
Edit because I like homework where the OP asks the right questions :)
Node* List::getNodeContaining(int searchValue)
{
Node* current = m_listHead;
while (current != 0 && current->number != searchValue)
{
current = current->next;
}
return current;
}
Node* List::getNodeAtPos(int position)
{
Node* current = m_listHead;
int pos = 0;
while (current != 0 && pos != position)
{
current = current->next;
pos++;
}
return current;
}
You list is very different from what a normal list ADT looks like. Rather than returning nodes, which would require the client know about the list implementation, you return and accept the type you're making a list of.
In this case you're making a list of integers, sou you'd want
public:
void add(int num); //prepends an Item to the list
int get(int pos);
The implementations of both are simple. Add makes a new node, and links it in;
void List::add(int num)
{
Node *newNode = new Node;
newNode->number = num;
newNode->next = m_listHead;
m_listHead = newNode;
m_listSize++;
}
Then get is easy too:
int List::get(int pos)
{
if(pos>m_listSize)
;//throw an error somehow
Node *tmp = m_listHead;
while(pos-->0)
tmp=tmp->next;
return m->number
}

linked list C++ , question selflearning

#include <iostream>
using namespace std;
struct Node
{
int item; // storage for the node's item
Node* next; // pointer to the next node
};
Node* addNode(Node*& head, int data , int& count)
{
Node * q; // new node
q = new Node; // allocate memory for the new mode
q->item = data; // inserting data for the new node
q->next = head; // point to previous node ?? how would i do that? ( am i doing it correctly?)
count++; // keep track of number of node
head = q;
return q;
}
int main()
{
int a, count=0;
int data;
bool repeat;
Node *head= NULL;
//^^ assuming thats creating the first node ^^
do
{
cout << "please enter the data for the next node" <<endl;
cin >> data;
addNode(head, data, count);
cout << "do you wish to enter another node? (enter true or false)" << endl;
cin >>repeat;
}
while (repeat == true);
// assuming this is the print function
while(head != NULL)
{
cout << "output" << temp->item << endl;
cout << temp->next << endl;
}
system("pause");
return 0;
}
okey i tried adding a new element in the list how would i move the head around like a LIFO memory (stack) so the last element is on the very top..
any help would be appreciated ! The pointers and the nodes are messing with my brain lately ....
temp is an uninitialized pointer. So -
temp-> item = a; // temp is not initialized or pointing to a memory location
// that has Node object to use operator ->
First, temp needs to be allocated memory location using new.
temp = new Node;
temp -> item = a;
And now assign it head. Similarly allocate memory for the child nodes too in the while loop. And return all the resources acquired from child to head using delete before program termination.
You seem to have some misunderstandings here:
Your "head" is the start of the list. It's always the start.
You add append elements to a linked list by assigning them to the last node's next pointer.
Third, you're not allocating anything.
Node *head= new Node();
Node *temp = new Node();
cout<<"enter something into data"<<endl;
cin >> a ;
temp->item = a;
head->next = temp;
Now ... to add the next thing, you either need to keep track of the last node (tail), or traverse the list to find the last node.
Node *nextNode = new Node();
nextNode->item = 0.0;
Node *i;
for (i = head; i->next != null; i = i->next);
i->next = nextNode;
This is O(n) execution time. By keeping track of the tail you make it O(1):
Node *head= new Node();
Node *tail = head;
Node *temp = new Node();
cout<<"enter something into data"<<endl;
cin >> a ;
temp->item = a;
tail->next = temp;
tail = temp;
Node *nextNode = new Node();
nextNode->item = 0.0;
tail->next = nextNode;
tail = nextNode;
EDIT: As pointed out, if you want to prepend to the list, you would:
temp->next = head;
head = temp;
Since I'm not sure every answer completely answers it, here's a linked list implementation (written without testig:
// your (correct) structure
struct Node
{
float item; // storage for the node's item
Node* next; // pointer to the next node
};
Now we need two pointers somewhere to look after the list:
/* some pointers */
struct List
{
Node* head;
Node* tail;
};
Now we need to create some elements. As others have said, you can do that with new:
/* create some elements we want to link in */
Node* elem1 = new Node();
Node* elem2 = new Node();
Node* elem3 = new Node();
/* maybe even set their properties! */
elem1->item = 3.14;
elem2->item = 3.14;
elem3->item = 3.14;
Notice how I didn't try to add these elements to a list yet? That's because I've got a function in mind which looks like this:
void addtolist(List &list, Node* node)
{
/* if no head, initialise the list */
if ( list->head == NULL )
{
list->head = node;
list->tail = node;
}
else if ( list->head != NULL && list->tail != NULL )
{
/* access the tail element and set its
next to this ptr.
Move tail to this node */
list->tail->next = node;
list->tail = node;
}
else
{
/* probably raise an exception! */
}
}
You can call this by doing this:
List l;
addtolist(l, elem1); /* etc */
Deleting elements is somewhat more tricky, since you have to go to that element, remember its previous element, grab it's next element, join them up and delete the Node* you're on.
Now for traversing lists... your terminology HEAD|TAIL reminds me of Erlang and tail recursion, where the current element is referred to as the head and the remainder the tail. If I write:
Node* cur = l.head;
while ( cur != NULL )
{
// do something with cur.item ?
cur = cur->next;
}
You can see this happening. Replacing cur with head here would be harmless thanks to the List struct.
Finally, I've used a very C-like approach here, but there's scope for templates:
template<typename T>
struct node
{
T item; // storage for the node's item
Node<T>* next; // pointer to the next node
};
and encapsulating the List struct as a class:
template<typename T>
class List
{
protected:
Node<T>* head;
Node<T>* tail;
public:
void addtolist(Node<T>* node);
Node<T>* gethead();
Node<T>* gettail();
}
Which brings you a little bit closer to std::list.
Additionally note that you are doing an implicit cast from int to float on
temp-> item = a;
as a is an int, while temp->item is a double.
To solve your problem: You want to allocate a new structure before accessing temp, thus
temp = new Node();