Linked List is Palindrome or not - c++

I'm new to Linked List and I was trying to solve this question where we have to return true or false on the basis of whether given linked List is palindrome or not.
Given a pointer to the 1st node.
bool isPalindrome(Node *head)
{
//Your code here
Node *startsecond = NULL;//will act as pointer to second Linked list
Node *temp2 = head;
Node *temp1 = head;
//Split LINKED LIST IN 2 PARTS
while(1){
temp2 = temp2->next->next;
if(temp2->next==NULL){//if linked list has odd no of elements
startsecond = temp1->next->next;
break;
}else{
startsecond = temp1->next;
break;
}
temp1 = temp1->next;
}
temp1->next=NULL;
//REVERSE THE SECOND LINKED LIST
Node *current = startsecond;
Node *prev = NULL, *next = NULL;
while(current!=NULL){
next = current->next;
current->next = prev;
prev=current;
current=next;
}
startsecond = prev;
while(head!=NULL && startsecond!=NULL){
if(startsecond->data == head->data){
head = head->next;
startsecond = startsecond->next;
}
else
return false;
}
return true;
}
I'm not able to understand it gives segmentation error. It says:
Runtime Error:
Runtime ErrorSegmentation Fault (SIGSEGV)
Here I'm first splitting the Linked List into 2 equal halves and then reverse the second half and then compare the elements to 2 one by one.
Can someone please help debug.

You have a typo here:
Node *temp2 = head, // , instead of ;
Node *temp1 = head;
Notice the , instead of a ;.
You need:
Node *temp2 = head;
Node *temp1 = head;
or
Node *temp2 = head, *temp1 = head;

Related

Inserting at the end in doubly linked list

**following is my linked list code...
its not working for some reason. Can someone help me out here?
void insertAtTheEnd(node *&head, int data){
node *newNode= new node(data);
newNode->data=data;
node *temp=head;
while(temp!=NULL){
temp=temp->next;
}
temp->next=newNode;
newNode->next=NULL;
newNode->prev=temp->next;
}
As you have it coded, temp is guaranteed to be NULL when your while loop exits. Hence, temp->next=NULL will crash.
When you probe for a position in the list, you typically need to keep "previous" variable to point to the item before the one you are iterating with.
node* temp = head->next;
node* previous = head;
while (temp)
{
previous = temp;
temp = temp->next;
}
// when the while loop returns, `previous` is the last element in the list
previous->next = newNode;
newNode->prev = previous;
newNode->next = nullptr;
Another case you missing in your code. When head is NULL (empty list), you need to update head to be your newNode
// empty list - return the new node as head
if (head == nullptr)
{
newNode->next = nullptr;
newNode->prev = nullptr;
head = newNode;
return;
}

What is the best way to reject duplicates in a sorted doubly linked list

I am trying to make a sorted doubly linked list that doesn't insert duplicates, but I am having trouble finding a way to do this. I looked at posts on how to remove duplicates, but no posts on preventing duplicate insertions.
Here is the code I have to insert and sort without rejecting duplicates. The parameter, dataIn takes values from a predefined Student object list in main (Student s = {{gpa, name}, ..., {gpa, name}}:
void StudentList::insertNode(Student dataIn)
{
ListNode *newNode; // A new node pointer
ListNode *pCur; // To traverse the list
// Allocate a new node and store num there.
newNode = new ListNode;
newNode->stu = dataIn;
newNode->forw = NULL;
newNode->back = NULL;
//Check if there is node in list
if(head ->forw == NULL && head->back == NULL){
head->forw = newNode;
newNode->back = head;
newNode->forw = head;
head->back = newNode;
}
else{
// Initialize pointers
pCur = head->forw;
// Find location: skip all nodes whose name is less than dataIn's name
while (pCur != head && pCur->stu.name < dataIn.name)
{
pCur = pCur->forw;
}
// Insert the new node between pPre and pCur
ListNode *pPre = pCur->back; // The previous node
newNode->back = pPre;
newNode->forw = pCur;
pCur->back = newNode;
pPre->forw = newNode;
}
// Update the counter
count++;
}
Does anyone know a way for rejecting duplicates without deleting? Thanks everyone!
What is the best way to reject duplicates in a sorted doubly linked list?
I suggest delaying the creation of the new ListNode until you know that the new node isn't a duplicate.
Assuming that the ListNode looks like this
struct ListNode {
Student stu;
ListNode *back;
ListNode *forw;
};
and that you have a head and tail ListNode* that is set to nullptr when the StudentList is empty, then the insertNode function could look like this:
bool StudentList::insertNode(const Student& dataIn) { // return true if node is inserted
ListNode* prev = nullptr;
ListNode* pCur = head;
// search for a good insertion spot
for(; pCur; prev = pCur, pCur = pCur->forw) {
if(dataIn.name == pCur->stu.name) return false; // equal, reject
if(dataIn.name < pCur->stu.name) break; // found a good spot before pCur
}
// delayed creation until here:
ListNode* newNode = new ListNode{dataIn, prev, pCur};
// linking
if(prev) prev->forw = newNode;
else head = newNode;
if(pCur) pCur->back = newNode;
else tail = newNode; // comment this line out if you don't have a "tail"
++count;
return true; // node inserted
}

Circular linked list: How to correct my remove node function?

I am learning circular linked list. I face a problem when calling deleteNodeByKey() to remove head node. It works for the rest of the nodes for remove. Why is it not working if remove node is head?
#include <iostream>
#include <stdlib.h>
using namespace std;
/* structure for a node */
struct node
{
int data;
struct node *next;
};
/* Function to insert a node at the begining of a Circular
linked list */
void push(struct node **head_ref, int data)
{
struct node *ptr = (struct node*)malloc(sizeof(struct node));
ptr->data = data;
ptr->next = *head_ref;
struct node *temp = *head_ref;
/* If linked list is not NULL then set the next of last node.
It is going to last node by circling 1 times.
*/
if(*head_ref != NULL){
while(temp->next != *head_ref){
temp = temp->next;
}
//set last node by ptr
temp->next = ptr;
}
else{
// 1 node circular linked list
ptr->next = ptr;
}
// after push ptr is the new node
*head_ref = ptr;
}
//get the previous node
struct node* getPreviousNode(struct node* current_node){
struct node* prev = current_node;
while(prev->next != NULL && prev->next->data != current_node->data ){
prev = prev->next;
}
return prev;
}
/* Given a reference (pointer to pointer) to the head of a list
and a key, deletes the first occurrence of key in linked list */
void deleteNodeByKey(struct node **head_ref, int key)
{
// Store head node
struct node* current_node = *head_ref, *prev;
while(current_node != NULL && current_node->data != key){
current_node = current_node->next;
}
if(current_node == NULL){
return;
}
//Removing the node
if(current_node->data == key){
prev = getPreviousNode(current_node);
prev->next = current_node->next;
current_node->next = NULL;
free(current_node);
return;
}
}
/* Function to print nodes in a given Circular linked list */
void printList(struct node *head)
{
struct node *temp = head;
if(head != NULL){
/*
do-while because at 1st temp points head
and after 1 rotation temp wil come back to head again
*/
do{
cout<<temp->data<<' ';
temp = temp->next;
}
while(temp != head);
cout<<endl;
}
}
int main() {
/* Initialize lists as empty */
struct node *head = NULL;
/* Created linked list will be 11->2->56->12 */
push(&head, 12);
push(&head, 56);
push(&head, 2);
push(&head, 11);
cout<<"Contents of Circular Linked List"<<endl;
printList(head);
deleteNodeByKey(&head, 11);
printList(head);
return 0;
}
Here is the code link: Source Code
Head node should not be the part of linked list, it should be a separate node which holds the address of the first node of the linked list. So when yo delete the first node make the Head point to the next of the first node and when you follow this structure the head-node will be same like other nodes.
declare head like this:
struct node* head;
head = *first;
To delete first
head = head->next;
free(first);`
In order to get around issues pertaining to deletion of head. I always found it useful to create a dummy node and set your head pointer to that.
node dummy;
dummy.next = *head_ref;
// Store head node
struct node* current_node = &dummy, *prev = &dummy;
current_node = current_node->next;
Once you are done with the operation set the head back to dummy.next. In this way you no longer need to keep track of the special case head, it can be treated as a normal node. Your code modified here: deletion with dummy node
inside deleteNodeByKey() function i add an if() block to re assign head node to it's next node:
//Removing the node
if(current_node->data == key){
//following if() is newly added
//key is inside head node
if(current_node == *head_ref ){
//changing the head point to next
*head_ref = current_node->next;
}
prev = getPreviousNode(current_node);
prev->next = current_node->next;
current_node->next = NULL;
free(current_node);
return;
}

Delete last node from single-linked list

I have to write a method that's going to delete the last node from the List. Do you guys have any ideas on how I should approach this?
If you have a single-linked list, you have no choice but to iterate through the entire list to the last node, maintaining a pointer to the previous node so you can reset its next field when freeing the last node:
if (head)
{
node *curNode = head;
node *prevNode = NULL;
while (curNode->next)
{
prevNode = curNode;
curNode = curNode->next;
}
if (prevNode) prevNode->next = NULL;
delete curNode;
}
If you were using a double-linked list instead, this would be easier, as you can keep a pointer to the last node in the list and just operate on it directly:
if (head == tail)
{
delete head;
head = tail = NULL;
}
else if (tail)
{
node *curNode = tail;
tail = curNode->previous;
tail->next = NULL;
delete curNode;
}
Of course, if you are really using C++ then you should be using the STL's std::list (double-linked) or std::forward_list (single-linked) containers instead, which handle these details for you.
To delete the last element on a list all you need to do is maintain two separate nodes. Initially one should point to the head of the list and the other should point to the second element on the list. You should do something like the following :
if(head == NULL)
return 0;
else if(head->next == NULL){
Node *temp = head;
delete temp;
head = NULL;
}
else{
Node *one = head;
Node *two = head->next;
while(two->next != NULL){
two = two->next;
one = one->next;
}
one->next = NULL;
delete two;
}

Building Huffman encoding tree from ordered list

I am building a huffman encoding tree from an ordered linked list (sorted by frequency of letters) that begins with the lowest frequency. After creating the tree, I traversed it and it appears that the tree was implemented incorrectly. When I traversed the tree, some of the nodes from the ordered linked list appeared to have be left out. (I don't think it was because my traversal is wrong.) Here is my code for the tree:
//My class for the nodes in the ordered linked list that will be converted to a tree
class fList{
public:
fList();
int frequency;
char letter;
fList* next;
fList* left;
fList* right;
};
fList::fList(){
frequency = 0;
letter = NULL;
next = NULL;
left = NULL;
right = NULL;
}
fList* head = NULL;
.
.
.
.
.
//Create the huffman encoding tree from the linked list stored in head
while(head->next != NULL){
fList *tree = new fList();
fList *temp = new fList();
fList *trail = new fList();
/* Take the first two frequency numbers, add them, create a new node
* with the total frequency number and have new node point to the first
* two nodes (right child and left child)
*/
total = (head->frequency + head->next->frequency);
tree->frequency = total;
//Set a new head node
tree->left = head;
tree->right = head->next;
head = head->next->next;
tree->left->next = NULL;
tree->right->next = NULL;
//place tree node in its correct place in sorted list
temp = head;
trail = temp;
if(head->frequency >= tree->frequency){
tree->next = head;
head = tree;
}
else if(temp->next != NULL){
while(temp != NULL){
if(temp->frequency >= tree->frequency){
tree->next = temp;
trail->next = tree;
break;
}
else{
trail = temp;
temp = temp->next;
}
}//while
//insert at the end of list
if(temp == NULL){
temp = tree->next;
trail->next = tree;
}
}//else if !=NULL
else if(head == NULL || head->next == NULL) head = tree;
}
At the end of the piece of code you posted, in the line
else if(temp->next = NULL && head != NULL) head = tree;
you inadvertently truncate the tree by setting temp->next = NULL where you probably meant to ask whether temp->next == NULL. This may be why some of the entries (the ones linked to by temp) are left out from the final result.