Okay so I'm working on a function that deletes a node that has the same name as the read in input. If it is a match that node must not be added to the new sequence.
So heres what I've got till now, my previous pointer is null at the end of the code i have no idea why
void deleteRecord (ifstream &batchfile, node *&h)
{
ofstream logfile;
logfile.open("freeplay.log", ios::app);
node *ptr = h;
node *previous = nullptr;
string term;
batchfile.seekg(1L, ios::cur);
getline(batchfile, term);
while (ptr)
{
if (!strstr(ptr -> name.c_str(), term.c_str()))
{
previous = ptr;
}
previous = previous -> next;
ptr = ptr -> next;
}
}
while (ptr)
{
if (!strstr(ptr -> name.c_str(), term.c_str()))
{
if(previous = nullptr){
previous = ptr;
head_previous = previous;
} else {
previous->next = ptr;
previous = previous -> next;
previous->next = null;
}
}
ptr = ptr -> next;
}
Here I have assigned previous to ptr whenever if is executed. For the first time, previous is same as ptr. From next on I am linking previous -> next to ptr.
Now after the loop, you can print the entire list of stored nodes whose head is previous_head;
Related
C++ noob reporting in. I'm trying to write a function that will create and initialize a doubly linked list using values that are stored in two different arrays. Here's how my linked list class is set up:
class node {
public:
node *prev;
node *next;
int key;
char type;
};
and here's how my dList class (containing various functions to alter my linked list) is set up:
class dList {
private:
node *head; // dummy head
node *tail; // dummy tail
public:
dList() { // default constructor, creates empty list
head = tail = NULL;
}
~dList() { // deconstructor
node *ptr = head;
while (head != NULL) {
head = head->next;
delete ptr;
}
tail = NULL;
}
dList(int arrayNums[], char arrayChars[], int size); // parametrized constructor, initialize list w/ contents of arrays
void addFront(int k, char t); // creates new node at front of list
void addBack(int k, char t); // creates new node at back of list
node *search(int k); // searches list for occurence of int parameter and returns pointer to node containing key
void find(char t); // outputs all keys that have type equal to character parameter, front to back
void moveFront(node* ptr); // moves node pointed to by parameter to front of list
void moveBack(node* ptr); // moves node pointed to by parameter to back of list
void out(int num, char = 'f'); // outputs first int elements of list, starting at front or back depending on char parameter
void sort(); // peforms a quick or mergesort on items; list should be in increasing order based on integer key
};
I need help implementing my parametrized constructor. Could someone tell me if the function I have now is written correctly? I think it is, but when I run my program, it runs forever--a clear problem. Here's my function as-is:
dList::dList(int arrayNums[], char arrayChars[], int size) {
node *newNode = NULL;
for (int i = 0; i < size; i++) {
if (head == NULL) {
newNode = new node;
newNode->key = arrayNums[i];
newNode->type = arrayChars[i];
newNode->prev = NULL;
newNode->next = NULL;
head = newNode;
tail = newNode;
}
else { // needs work!
newNode = new node;
newNode->key = arrayNums[i];
newNode->type = arrayChars[i];
newNode->prev = tail;
tail->next = newNode;
tail = newNode;
}
if (i == (size - 1)) {
tail->next = NULL;
}
}
}
Thank you very much!
EDIT: here is my main.cpp (code I'm using to test my dList.cpp file)
#include <iostream>
using namespace std;
#include "dList.cpp"
#define SMALL 200
#define MAX 100000
#define ROUNDS 100
int main(){
int i, x[MAX];
char ch[MAX];
for(i=0;i<SMALL;i++) {
x[i] = 2 * (SMALL - i);
ch[i] = 'a' + (i % 26);
}
dList A(x,ch,SMALL), B;
A.out(10);
node *tmp = A.search(2*SMALL-8);
A.moveFront(tmp);
A.out(10);
A.moveBack(tmp);
A.out(10);
A.find('b');
A.sort();
A.out(10);
A.out(10,'b');
A.addBack(500,'d');
A.addFront(501,'z');
A.out(10);
A.out(10,'b');
B.addFront(1,'a');
B.addBack(2,'b');
B.out(2);
for(int j=0; j<ROUNDS; j++){
cout << endl << "round " << j << endl;
for(i=0;i<MAX;i++) {x[i] = 2*MAX-i; ch[i] = 'a'+ (i%26);}
dList A(x,ch,MAX);
node *tmp = A.search(2*MAX-8);
A.moveFront(tmp);
A.moveBack(tmp);
A.sort();
A.out(10);
A.out(10,'b');
}
}
I have a file that contains English words in a txt file, each word in a new line.
I'm a beginner in C. I'm using a load and unload functions to store all the words into a hashtable (separate chaining) and unload them from memory, but has ran into some problems.
The functions (the code in main.c is correct):
load:
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include "dictionary.h"
#define SIZE 26
typedef struct node
{
char word[LENGTH+1];
struct node *next;
}node;
unsigned int hash_num = 0;
node *hashtable[SIZE]; //26 letters in alphabet
node *head = NULL;
// hashfunction
unsigned int hash(char const *key)
{
unsigned int hash= tolower(key[0]) - 'a';
return hash % SIZE;
}
/**
* Loads dictionary into memory. Returns true if successful else false.
*/
bool load(const char* dictionary)
{
unsigned int hash_index=0;
FILE *fp = fopen(dictionary, "r");
if(fp == NULL)
{
fprintf(stderr, "Couldn't open %s",dictionary);
return false;
}
//dictionary
while(!feof(fp))
{
node *temp = malloc(sizeof(node));
if (temp == NULL)
{
unload();
fclose(fp);
return false;
}
if(fscanf(fp , "%s", temp->word) == 1) //storing word of dictionary in my new_node -> word
{
hash_index = hash(temp->word);
head= hashtable[hash_index]; //head always points to first element of linked list (containting word of dictionary)
temp->next = head;
head = temp;
hash_num++;
}
else //if fscanf couldn't store the word (return 0)
{
free(temp); //free last temp
break;
}
}
fclose(fp);
return true;
}
unload:
bool unload(void)
{
for(int i=0; i<SIZE; i++)
{
if(hashtable[i] != NULL) //if hashtable isn't NULL (has nodes)
{
node *cursor = hashtable[i]; //cursor points at head of individual linked list
while(cursor != NULL) //free them
{
node *temp = cursor;
cursor = cursor->next;
free(temp);
}
}
}
return true;
}
Can anyone tell me if the logic is correct? Whenever I run valgrind it tells me that all my nodes were allocated but just 3 free'd.
total heap usage: 143,094 allocs, 3 frees, 8,014,288 bytes allocated
LEAK SUMMARY:
==15903== definitely lost: 8,013,040 bytes in 143,090 blocks
==15903== indirectly lost: 0 bytes in 0 blocks
==15903== possibly lost: 0 bytes in 0 blocks
When checking the provided source code (missing "dictionary.h"), the main problem is locating in the load() function.
Problem 1 (Main) - the hashtable[] is never updated when adding a new word/node (after computing hash_index = hash(temp->word);).
To store the updated linked-list (managed as reversed), it is
necessary to update the hashtable[hash_index] with the new node
pointer (the allocated temp node).
temp->next = head;
head = temp;
hashtable[hash_index] = head; // update the hashtable[] pointer
hash_num++;
Alternate solution without global variable head.
temp->next = hashtable[hash_index]; //head always points to first element...
hashtable[hash_index] = temp; // update the hashtable[] pointer
hash_num++;
Instead of
temp->next = head;
head = temp;
hash_num++;
Problem 2 (Small) - the hashtable[SIZE] is never initialized.
In the unload() function, in the for-loop, the if-condition
if(hashtable[i] != NULL) assumes that each item of the array is
initialized to NULL.
Add at the beginning the load() function or before calling it, a for-loop to initialize each pointer.
for(int i=0; i<SIZE; i++)
{
hashtable[i] = NULL;
}
Problem 3 (Potential Bug Source) - as suggest by reviewer, the use of head, declared as a global variable node *head = NULL; could be a potential source of bug.
In the load() function, the variable head is used as a temporary
storage but could store value during software run. If a read operation
is performed without a well-known write operation before, the result
could be an unexpected error even if the compilation doesn't detect
error or warning.
The best way is to reduce the number of global variable as much as
possible.
Enhancement (Reverse the linked-list) - because the managed linked-list is adding new items in the front, here is a solution to add new items in the end.
node *first = hashtable[hash_index];
if (first == NULL) {
hashtable[hash_index] = temp;
}
else {
temp->next = NULL; // ending the list
while (first->next!=NULL) {
first = first->next; // loop until last node
}
first->next = temp; // linking to the last node
}
hash_num++;
Instead of
head= hashtable[hash_index]; //head always points to first element ...
temp->next = head;
head = temp;
hash_num++;
Given a linked list as a->x->b->y->c->z , we need to reverse alternate element and append to end of list. That is , output it as a->b->c->z->y->x.
I have an O(n) solution but it takes extra memory , we take 2 lists and fill it with alternate elements respectively , so the two lists are a b c and x y z and then we will reverse the second list and append it to the tail of first so that it becomes a b c z y x .
My question is can we do it in place ? Or is there any other algorithm for the same ?
The basic idea:
Store x.
Make a point to b.
Make y point to the stored element (x).
Make b point to c.
etc.
At the end, make the last element at an odd position point to the stored element.
Pseudo-code: (simplified end-of-list check for readability)
current = startOfList
stored = NULL
while !endOfList
temp = current.next
current.next = current.next.next
temp.next = stored
stored = temp
current = current.next
current.next = stored
Complexity:
O(n) time, O(1) space.
Here is logic in recursion mode
public static Node alRev(Node head)
{
if (head == null) return head;
if (head.next != null)
{
if (head.next.next != null)
{
Node n = head.next;
head.next = head.next.next;
n.next = null;
Node temp = alRev(head.next);
if (temp != null){
temp.next = n;
return n;
}
}
else
return head.next;
}
else
return head;
return null;
}
This is a recent question from amazon interview, the Idea looks good and there seems to be no trick in it.
Java code with comments:
static void change(Node n)
{
if(n == null)
return;
Node current = n;
Node next = null, prev = null;
while(current != null && current.next != null)
{
// One of the alternate node which is to be reversed.
Node temp = current.next;
current.next = temp.next;
// Reverse the alternate node by changing its next pointer.
temp.next = next;
next = temp;
// This node will be used in the final step
// outside the loop to attach reversed nodes.
prev = current;
current = current.next;
}
// If there are odd number of nodes in the linked list.
if(current != null)
prev = current;
// Attach the reversed list to the unreversed list.
prev.next = next;
}
here the c code which don't uses any extra space for doing this..enjoy and have fun
in case of any doubt feel free to ask
#include<stdio.h>
#include<stdlib.h>
int n;
struct link
{
int val;
struct link *next;
};
void show(struct link *);
void addatbeg(struct link **p,int num)
{
struct link *temp,*help;
help=*p;
temp=(struct link *)malloc(sizeof(struct link));
temp->val=num;
temp->next=NULL;
if(help==NULL)
{
*p=temp;
}
else
{
temp->next=help;
*p=temp;
}
n++;
show(*p);
}
void revapp(struct link **p)
{
struct link *temp,*help,*q,*r;
r=NULL;
temp=*p;
help=*p;
while(temp->next!=NULL)
{
temp=temp->next;
q=r; //this portion will revrse the even position numbers
r=temp;
temp=temp->next;
//for making a connection between odd place numbers
if(help->next->next!=NULL)
{
help->next=temp;
help=help->next;
r->next=q;
}
else
{
r->next=q;
help->next=r;
show(*p);
return;
}
}
}
void show(struct link *q)
{
struct link *temp=q;
printf("\t");
while(q!=NULL )
{
printf("%d ->",q->val);
q=q->next;
if(q==temp)
{
printf("NULL\n");
return;
}
}
printf("NULL\n");
}
int main()
{
n=0;
struct link *p;
p=NULL;
// you can take user defined input but here i am solving it on predefined list
addatbeg(&p,8);
addatbeg(&p,7);
addatbeg(&p,6);
addatbeg(&p,5);
addatbeg(&p,4);
addatbeg(&p,3);
addatbeg(&p,2);
addatbeg(&p,1);
revapp(&p);
return 0;
}`
Here's my simple linked list program that creates a doubly linked list, and it works.
#include <iostream>
using namespace std;
typedef struct node {
int data;
node *next;
node *prev;
}node;
void printList(node *temp);
int main()
{
node *head;
head = new node;
head->prev = NULL;
node *next = head;
node *prev = head;
node *temp = head;
node *current = head;
//creates 100 nodes, last one points to next
for(int x = 0; x<100; x++)
{
temp->data = x;
current = temp;
temp = new node;
current->next = temp;
temp->prev = current;
temp->next = NULL;
}
//=========================================
printList(head);
//=========== set everything to head ===========
current = head;
prev = head;
//============= reverses linked list ============
while(current->next != NULL)
{
next = current->next; //moves next pointer to next node
current->prev = next; //points current's previous to next node
current = next; //set current pointer to next node
current->next = prev; //set current's next to previous node
prev = current; //move prev node up to current
}
//================================================
printList(head);
cout<<"done";
return 0;
}
void printList(node *temp)
{
while(temp->next != NULL)
{
cout<<temp->data<<'\n';
temp = temp->next;
}
}
Once I add the reverse function though, it hangs. Actually, the function itself works, but in an IDE, when I LOOP it, it prints out all the values, then just hangs(sits there with blinking cursor) and does nothing.
Solution: Got it to work. This is what my function ended up being.
current = head; //set current pointer to head
prev = head; //set previous pointer to head
next = current->next; //moves next pointer to next node
current->next = NULL; //set the next of the header to NULL, because it will actually be the last
//node of reversed list.
current->prev = next; //set previous of the header to the next node.
while(next != NULL)
{
current = next;
next = current->next;
current->prev = next;
current->next = prev;
prev = current;
}
Your reverse algorithm is basically broken.
On the first pass through:
current = head; // Current is pointing at node 0, node0->next is 1 from before
prev = head; // Prev is pointing at node 0
next = current->next; // next is pointing at 1
current->prev = next; // node0->prev is pointing at 1
current = next; // current is pointing at 1
current->next = prev // node1->next is pointing at 0
then next pass
next = current->next // read up there ^^^ node1->next is pointing at 0
... so next goes back to to node 0.
That is not what you meant to do - it causes you to loop around nodes 1 and zero repeatedly, instead of progressing to node 2 and beyond...
Note that you could have easily debugged this if you put this code into the reverse loop:
cout<<"\nStarting iteration"
cout<<"\nNext is at" << next->data
cout<<"\nCurrent is at" << current->data
cout<<"\nCurrent->next is" << current->next->data
etc... doesn't take long to type, reveals all :)
(probably you would cut it down to do 3 instead of 100)
I just did the steps for 3 nodes manually (on paper) to deduce this answer...
Look this simple solution..
Node* Reverse(Node* head)
{
Node * curr=head;
Node * prev=NULL,* nxt=NULL;
while(curr!=NULL)
{
nxt=curr->next;
curr->next=prev;
curr->prev=nxt;
prev=curr;
curr=nxt;
}
return prev;
// Complete this function
// Do not write the main method.
}
There is a singly connected linked list and a block size is given.For eg if my linked list is 1->2->3->4->5->6->7->8-NULL and my block size is 4 then reverse the first 4 elements and then the second 4 elements.The output of the problem should be 4->3->2->1->8->7->6->5-NULL
I was thinking of dividing the linked list into segments of size 4 and then reversing it.
But that way I am forced to use a lot of extra nodes which is not desired at all.
The space complexity should be kept to a minimum.
It will be highly appreciable if someone can come with a better solution where the usage of extra nodes would be kept to a minimum.
I tried this...seems to work fine...
node* reverse(node* head) // function to reverse a list
{
node* new_head = NULL;
while(head != NULL)
{
node* next = head->next;
head->next = new_head;
new_head = head;
head = next;
}
return new_head;
}
node* reverse_by_block(node* head, int block)
{
if(head == NULL)
return head;
node* tmp = head;
node* new_head = head;
node* new_tail = NULL;
int count = block;
while(tmp != NULL && count--)
{
new_tail = tmp;
tmp = tmp->next;
}
new_tail->next = NULL;
new_tail = new_head;
new_head = reverse(new_head);
new_tail->next = reverse_by_block(tmp,block);
return new_head;
}
You can advance swapping the current element with the next 3 times: 1234, 2134, 2314, 2341. Then do it twice to get 3421. Then once to get 4321. Then advance 4 steps and repeat the process with the next block.
This can be done in linear-time, with constant space.
Here is a brief description:
Split the linked list into two parts by block-size
int split(node* head, node** listA, node** listB size_t block_size)
{
node* cur = head;
while(block_size && cur)
{
cur = cur->next;
--block_size;
}
if(!cur) { /* error : invalid block size */ return -1; }
*listA = head;
*listB = cur->next;
cur->next = NULL; /* terminate list A */
return 0;
}
Reverse the two sub-parts, (use a non-recursive linear time, constant space function)
reverse(listA);
reverse(listB);
Link them to get the desired linked list.
cur = *listA;
/* goto last but one element of listA */
while(cur->next) cur = cur->next;
cur->next = *listB;