I'm currently trying to write a data structure framework for myself. Deletion of the second largest node from a singly linked list works flawlessly in ordinary cases. But fails in a particular one. Here's what I've already tried :
//node.h
typedef struct Node {
int value;
struct Node *nextNode;
} Node;
//linkedlist.h
typedef struct LinkedList{
Node *head;
int count;
} LinkedList;
//liblinkedlist.c
int deleteSecondLargest(LinkedList *list){
if(list->count==0)
return 1;
if(list->count==1)
return 2;
Node *temp = list->head;
Node *largest = temp;
Node *prev = NULL;
Node *prev1 = NULL;
Node *ptr = temp;
//finding the second largest node
while(temp!=NULL){
if(temp->value > largest->value){
largest = temp;
}
else if((temp->value!=largest->value) && (temp->value > ptr->value)){//here's the code failing
prev1 = prev;
ptr = temp;
}
prev = temp;
temp = temp->nextNode;
}
//deleting it
if(ptr==list->head)
list->head = list->head->nextNode;
else
prev1->nextNode = ptr->nextNode;
free(ptr);
list->count--;
return 0;
}
The code fails in the commented block whenever the items in the list are in the order of 1332->34->N.
I can understand why it is failing because both temp and ptr is holding 1332 and else if is returning false in the second iteration, but I can't find any solution to it. Also, the files in which the functions reside has been commented above the function definition.
Any help?
As far as I see, you have a problem with the first part of your code: finding the second-largest element in a single-linked list.
In fact, there're three problems in this code:
The ptr is initialized with first element, which may be too large to be the second maximum.
No node is ever demoted from largest to ptr. That means, for list 34 -> 1332 -> N your code also does not work.
If two maximums have equal values, second one is ignored. That means, for list 123 -> 123 -> N your code also does not work.
The algorithm of finding two maximums works as follows:
Initialization: initialize two current maximums with the lowest possible values or special "uninitialized" flag.
In loop over all the elements:
Update both maximums using the current value.
Implementation:
// Initialization
Node *largest = nullptr; // for maximum, nullptr means "not initialized"
Node *largest2 = nullptr; // for second maximum, nullptr means "not initialized"
Node *prev_largest = nullptr; // for previous node for maximum
Node *prev_largest2 = nullptr; // for previous node for second maximum
// Iterations
for (Node *cur = list->head, *prev = nullptr; // start of the loop: current node is head, prev is null
cur != nullptr; // end of the loop: current node is null
prev = cur, cur = cur->nextNode) { // loop iteration: move both current and prev nodes forward
if (largest == nullptr || cur->value > largest->value) { // check if we need to update maximum
// the node which was maximum is now second maximum
prev_largest2 = prev_largest;
largest2 = largest;
// current node is now maximum
prev_largest = prev;
largest = cur;
} else if (largest2 == nullptr || cur->value > largest2->value) { // check if we need to update second maximum
// current node is now second maximum
prev_largest2 = prev;
largest2 = cur;
}
}
// End of algorithm
// Second maximum is now in variable largest2
// Previous node for second maximum is now in variable prev_largest2
Also, please note this algorithm works even if your list contains less than 2 elements (in this case largest2 will be nullptr at the end).
Related
So I have a problem with my head node changing when I add a new node to the list. I have to read in multiple lines from a file. Each line is going to be a function f(x) = ... and the nodes are singular expressions in the function so node 1 for example can be 25x^2 and node 2 could be 15x. So my Node class holds the coefficient so for node 1 it would be 25, and the exponent x goes to. Here's the pieces of code that are causing the problem I think.
Node* n = new Node();
List nodeList;
nodeList.setHead(NULL);
while(not at the end of line)
{
//This while loop just inputs from file, and stores values into Node class.
if(!nodeList.getHead()) //so this is first node being input.
{
//i collect the values for coefficient and exponent here...
n->setCoef(coef);
n->setExp(exp);
nodeList.insertNode(n);
}
else //so this is not the first node in the list.
{
//i collect the values for coefficient and exponent again here...
//After this code below, the head node changes to n's coef and exp.
//I know this is because n is still pointing at the head node
//but I keep getting runtime errors when trying to fix this.
n->setCoef(coef);
n->setExp(exp);
nodeList.insertNode(n);
}
}
Here is my List::insertNode(Node* n) class:
void List::insertNode(Node* n){
//if theres no head node, just set it to the n node and continue.
if (!head)
head = n;
else{
Node* ptr = head; //used to traverse through list.
bool likeTerms = false;
while(ptr) //This while loop checks to make sure theres no like terms.
{
if (ptr->getExp() == n->getExp()){
likeTerms = true;
break;
}
ptr = ptr->getNext();
}
//If they aren't like terms, just add the node to the end.
if (!likeTerms){
ptr = head;
while(ptr->getNext() != NULL)
{
ptr = ptr->getNext(); //traverses to the last node in list.
}
ptr->setNext(n); //Adds the new node to the spot after the last node
}
else if (likeTerms == true)//If the x exponents have like terms,
//then just combine them.
ptr->setCoef(ptr->getCoef()+n->getCoef());
}
}
The code to insert node for each line can also be simplified as following since the two statements of if-else condition are equivalent. The variable of Node* n need to be created in the while-loop or the nodeList would contain only one node with the last item of the function f(x).
while (not at the end of line)
{
Node* n = new Node;
n->setCoef(coef);
n->setExp(exp);
nodeList.insertNode(n);
}
The function void List::insertNode(Node* n) can also be simplified. The following is the simplified version.
void List::insertNode(Node* n) {
Node* ptr = header;
Node* prev = NULL;
bool same_exp_occurred = false;
while (ptr) {
if (n->getExp() == ptr->getExp()) {
ptr->setCoef(ptr->getCoef()+n->getCoef());
same_exp_occurred = true;
break;
}
prev = ptr;
ptr = ptr->getNext();
}
if (!same_exp_occurred && prev) {
prev->setNext(n);
}
}
I have to face this problem: I have a doubly linked list and I have to make insertion at the tail. My list is made of Nodes such as
struct Node {
int val; // contains the value
Node * next; // pointer to the next element in the list
Node * prev; // pointer to the previous element in the list
};
and my class list declares only
private:
Node * first; // Pointer to the first (if any) element in the list
at first.
Now, I wrote such a method for inserting:
void List::insert(int n){
Node * tmp = new Node;
tmp->val = n;
tmp->next = 0;
if (!first) {
first = tmp;
}
else {
Node * p = new Node;
p = first;
while (p->next) {
p = p->next;
}
p->next = tmp;
tmp->prev = p;
}
};
and if I take several numbers from cin (say, 1 2 3 4), I call insert but I end up not having all the elements I wanted to store. I have only first and tmp, which contains the last number from the input (e.g. 4).
I struggle to figure out what's wrong - my first suggestion is variable scope.
Or is there anything wrong during the pointer setting?
OBS: I'd use a tail pointer of course, but the aim is traversing the list.
Any feedback is really appreciated.
I'm trying to implement my own linked list using vectors and pointers. The problem I'm have is that I can't get the first node to point to the second node.
Here's my code and what I've tried:
struct Node {
Node* previous;
Node* next;
int data;
};
// Initialize: Create Vector size 20 and first node
void LinkedList::init() {
vecList.resize(20, NULL); // Vector of size 20
Node* head = new Node(); // Create head node
head->previous = NULL; // Previous point set to null
head->next = vecList[1]; // Next pointer set to next position
head->data = 0; // Data set at value 0
vecList[0] = head; // Put head node in first position
count = 1; // Increase count by 1
}
// Add Node to array
void LinkedList::push_back(Node* node, int data) {
count += 1;
node = new Node();
node->next = vecList[count + 1];
node->previous = vecList[count - 1];
node->data = data;
vecList[count - 1] = node;
}
The data has been passed in and will displayed using:
cout << linkedlist.vecList[1]->data << endl;
But if I try this way to display I get error saying the next pointer is <Unable to read memory>
cout << linkedlist.vecList[0]->next->data << endl;
You forgot to set the next pointer of the previous Node in the push_back method.
If count is a member variable of the list containing the number of entries you have to change the method like this:
EDIT: actually you have to increment count in the end because array indices start with zero.
void LinkedList::push_back(Node * node, int data){
node = new Node();
node->next = NULL; // NULL because next element does not exist yet
node->previous = vecList[count - 1];
node->data = data;
vecList[count] = node;
vecList[count-1]->next = vecList[count];
count++;
}
Still it's a bit strange that you try to implement a linked list with a vector or array because that actually defeats the advantages of a list...
It looks like vecList is a vector/array of pointers to Node.
When you init, you let the first element point to the second element:
void LinkedList::init(){
...
head->next = vecList[1];
But at this point, the second element does not exist yet. So you cannot point to it yet. Something similar is wrong at the push_back function.
With single loop how can we print last 3rd element from given single linked list
lets take there are 10 node in give linked list and i am supposed to find last 3rd node?
below code is for inserting a node at beginning now how can i print last 3rd element with sing loop? please help me
struct node
{
int data;
struct *next; //hold address of next node
}
void insert_begin(struct node**ptr)
{
node *temp;
temp=(struct *node) malloc(sizeof(struct node));
cout<<"enter ur data"<<endl;
cin>>temp->data;
temp->next=*ptr;
*ptr=temp;
}
int main()
{
node *head=0 // making head node or 1st node null
insert_begin(&head);
insert_begin(&head);
insert_begin(&head);
.....upto 10
}
Keep three pointers:
node * prevPrev = null;
node * prev = null;
node * current = head;
Iterate over the list with current until current->next is null.
At each iteration, update prev and prevPrev
prevPrev = prev;
prev = current;
current = current->next;
When current->next is null, prevPrev points to the last 3rd element.
You could use two pointers *p1,*p2 and initialize them so that *p1 points to the first element and *p2 points to the third element of your list. Then loop until *p2 reaches the end of your list, moving both pointers to the next element in each loop. When *p2 reaches the end print the element pointed by *p1.
OK, to do this in easy way what you can do is first manage counter variable for length of link i.e. 'count'. now:
int len = count;
*temp = ptr;
while(tmp->next != null)
{
len--;
if(len==3)
{
//you are at the last third element
// do your work and break the loop
}
else
{
temp = temp->next;
}
}
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
}