Merging two linked lists yielding seg faults, etc - c++

I'm creating a linked list of state objects, each of which contains a linked list of resident objects who live in that state. The user reads in a database file and then can choose from a handful of commands, such as finding a person, moving a person, or merging two states into a brand-new state. When I try to merge the people of 2 states, I have to create a new state, move all of the people from the first state's resident list to the new state's resident list and do the same with the resident list of the second state. The people should then appear in the new state's resident list but not in the resident lists of the original states. I'm getting a bunch of errors: when I try merging, I get repetitive free chunk warnings; when the user tries to print out the new state's resident list as a command, no one is listed; further, when the user tries to print either of the original states' resident lists, the first few are printed but then there's a set fault, the core gets dumped, and the program stops running. Any help would be greatly appreciated.
In my list object:
void addLink (Link <type> * data) {
if (first == NULL) {
first = data;
last = data;
}
else {
last->next = data;
last = data;
}
}
And in my main, if the command typed was "merge"...
else if (cmd == "merge") {
string state1, state2, newstate;
cin >> state1 >> state2 >> newstate;
State * ns = state_ls->addLink(new State(newstate))->data;
Link <State*> * s1 = searchList(state1, state_ls);
Link <State*> * s2 = searchList(state2, state_ls);
List <Person*> people1 = s1->data->res_list;
List <Person*> people2 = s2->data->res_list;
List <Person*> newres_list = ns->res_list;
Link <Person*> * temp = people1.first;
while (temp != NULL) {
newres_list.addLink(temp);
temp = temp->next;
}
temp = people2.first;
while (temp != NULL) {
newres_list.addLink(temp);
temp = temp->next;
}
}

A few issues in your code which could be the cause of your problems:
You don't check the result of searchList(). What if the state you enter doesn't exist and it returns NULL? Similarly for addLink() if it can fail.
people1, people2 and newres_list are copies of the original lists. Depending on how these classes are implemented this can be bad or very bad. You probably want to use pointers or references here, like:
List <Person*>& people1 = s1->data->res_list;
List <Person*>& people2 = s2->data->res_list;
List <Person*>& newres_list = ns->res_list;
If you wish to move persons from the original states to the new state you need to reset the person list head/tail after you move them. Probably something like:
s1->person->data->res_list->first = NULL;
s1->person->data->res_list->last = NULL;
s2->person->data->res_list->first = NULL;
s2->person->data->res_list->last = NULL;
Update -- You seem to be a little confused about linked list pointers and adding/removing nodes from multiple lists. If we look at a simple example:
List<Person*>* Person1 = new List<Person*>;
List<Person*>* Person2 = new List<Person*>;
List<Person*> List1;
List<Person*> List2;
List1.addLink(Person1);
List1.addLink(Person2); //Ok: List1 has two persons
List2.addLink(Person1); //Error: Person1 can't belong to both lists
Everything is fine until you try adding a node already in one list to another list. This will "mess up" your node next pointers in both lists.
Another confusion seems to be how to move all elements from one list to another. All you have to do is to set the head/tail of both lists, for example to move all nodes from List1 to List2 just do:
List2.first = List1.first;
List2.last = List1.last;
List1.first = NULL;
List1.last = NULL;
You don't need to touch the individual nodes in List1 as you aren't changing their pointer locations. If you want to copy all the nodes from List1 to List2 it is a bit different as you have to create new nodes.
If you are still having problems with your corrected code I would suggest reducing it to a small example that exhibits the problem and post another SO question.

Related

why do we use pos in c++? assume by my code int pos = cHash(symbol);

so I was doing a program of SymbolTable for my compiler course ....I landed with a problem of pos ...why do we use it on the first place? TIA <3
void insert(char *symbol, char *type)
{
int pos = cHash(symbol);
if (block[pos] == NULL)
{
block[pos] = new SymbolInfo();
block[pos]->symbol = symbol;
block[pos]->type = type;
block[pos]->next = NULL;
}
else
{
SymbolInfo *newNode = new SymbolInfo();
newNode->symbol = symbol;
newNode->type = type;
// pointer swap
SymbolInfo *nextNode = block[pos];
block[pos] = newNode;
newNode->next = nextNode;
}
}
The code here implements what’s called a chained hash table. We maintain an array of linked lists, and use the function cHash to assign each symbol to one of those linked lists.
The advantage of storing things this way is speed. If we put everything into a single linked list, then the average cost of looking something up is O(n), where n is the number of items in the list, since on average we have to look at at least half the items in the list. But by having multiple linked lists (say, b of them) and distributing items across them more or less randomly, we decrease the average cost of a lookup to O(1 + n/b), which is a lot faster if b is roughly the same order of magnitude as n.
If there is no element in the chain then new element is added in front,
otherwise through hashing if we reach a chain or, bucket that contains an element then we insert the new element at the beginning of the chain and
the rest of the elements is linked to the end of new node.

Is there any way to make both unsorted and sorted linked list by only adding single struct instance

void addTutorIntoBeginning(int TID, std::string tutorName, std::string dateJoined, double hourlyRate, std::string phone, std::string address, std::string tuitionCode, std::string subjCode, double rating)
{
tutor* newTutor = createTutor(TID, tutorName, dateJoined, hourlyRate, phone, address, tuitionCode, subjCode, rating);
//check if list is empty
if (head == NULL)
{
head = newTutor;
tail = newTutor;
size++;
}
else
{
newTutor->next = head;
head->prev = newTutor;
head = newTutor;
size++;
}
}
the adding function is for unsorted list. What if the unsorted list has gone through sorted process, is it possible to revert back the sorted list to the unsorted list (since the next and prev pointers are pointed to different instance after sorted) without creating 2 different lists which that one is an unsorted list and another is a sorted list that need to create two newTutor instances at the same time when performing the adding function.
Or the best way is to actually create two different list instead?
Sorry if the wording is bad.

Create a checkerboard or "Interweave" two linked-lists. IE changing the pointers of two linked lists

So I have two linked lists, each holding a color:
1.black->2.black->3.black->4.black->5.black->NULL
1.red ->2.red ->3.red ->4.red ->5.red ->NULL
I want the function to return
1.black->2.red ->3.black->4.red ->5.black->NULL
1.red ->2.black->3.red ->4.black->5.red ->NULL.
Lets name the first pointers, firstBlack and firstRed. To achieve this "checkerboard" pattern, I switch the nodes that each first is pointing to with a simple swap to the other list, advance the pointer two spots, then repeat until I'm at the end of the list.
while(firstBlack->next != NULL && firstRed->next != NULL) {
Node * temp = firstBlack->next;
firstBlack->next = firstRed->next;
firstRed->next = temp;
firstBlack = firstBlack->next->next;
firstRed = firstRed->next->next;
}
However, the function isn't doing what it's supposed to although I'm fairly certain that my logic is correct. I am also getting seg faults :(
This is a simple enough code, please use a debugger and debug the code step by step.
Also please post the entire code not just what's in the while loop.
This code should work correctly.
//Some methods to create these linked lists.
pBlackHead = CreateBlackList();
pRedHead = CreateRedList();
firstBlack = pBlackHead;
firstRed = pRedHead;
while(firstBlack->next != NULL && firstRed->next != NULL){
Node * temp = firstBlack->next;
firstBlack->next = firstRed->next;
firstRed->next = temp;
firstBlack = firstBlack->next;
firstRed = firstRed->next;}
While printing the list to check the correctness use pBlackHead , pRedHead. A debugger is not currently available on the system I am using but this should work.
You are advancing two steps without checking end conditions. Because you have an odd number of items, you dereference a null pointer.
You don't need to care which tail originated in which list to swap them
for(; left->next && right->next; left = left->next, right = right->next) {
std::swap(left->next, right->next);
}

Deleting elements from doubly bounded pointer list

I am working on a project where I create a double bounded pointer list, delete several elements, and still be able to read off the list. I have a double bounded pointer list, but am having trouble deleting elements and keeping the list double bounded. This then causes issues when trying to print the list.
Below is the IF statement I've placed in a while loop to help delete unwanted elements. I keep getting a segmentation fault (core dumped).
if ((black2 != black)||(white2 != white)) {
dump = help;
help = help ->next;
dump -> before = temp;
temp -> next = help;
help ->before = temp;
delete dump;
}//if
else { temp = help;
help = help->next;
help ->before = temp; }//else
To maintain properly the doubly linked list you should do something like :
void remove(X *elt) {
X* before = elt->before;
X* after = elt->next;
if (before != NULL) { // assuming first element points to NULL
before->next = after;
}
else {
first = after; // assuming first is a pointer to first element of list
}
if (after != NULL) { // assuming last element points to NULL
after->before = before;
}
else {
last = before; // assuming last is a pointer to last element
}
delete elt;
}
That way, you ensure that elements around current correctly point to each other dealing with special cases of removing first or last element.
But you already have a std::list template in Standard Template Library
One logical issue in your code is the line dump->before = temp.
What this does is that it sets the previous node pointer of dump to temp, as opposed to defining temp as the previous node.
The correct line should read temp = dump->before
PS: Your code is correct assuming that the node you are deleting isn't the first or last node (and you haven't padded with dummy nodes). You should introduce checks for these cases if required.

Need help making a linked list program

So I have an assigment that consist of making a program that allows me to enter the integer 10 on a linked list after finding the value 10 on the list three times. The 10 that I have to insert needs to go after the third 10. The code that I made for this program is the following:
Linkedlist<int>*prt=new LinkedList<int>;
bool found = false;
int count;
while(ptr==NULL & !found)
{
if (ptr -> info == 10)
count ++;
if(count == 3)
found = true;
if(!found)
ptr = ptr -> next;
Node NewNode = new Node;
if(count == 3)
NewNode -> info = 10;
NewNode -> next = ptr -> next;
ptr -> next = NewNode;
}
I think the code I made is correct, however, I am kind of lost on how to turn this piece of code into a running program. Any help would be greatly appreciated.
You have multiple errors in your program. For one, the variable prt should probably be ptr. Also, your while condition should be using the && boolean operator instead of the & bitwise operator. From your description, it appears that the last two lines of your loop:
NewNode -> next = ptr -> next;
ptr -> next = NewNode;
Should only be invoked if count == 3. However, in it's current form they are being executed on every loop iteration. Likewise, you should only create a NewNode when you actually plan to do the insertion.
You're also checking the condition count == 3 multiple times including indirectly through the found variable. Each of these conditions could be collapsed into a single if like so:
if (count == 3) {
found = true;
Node NewNode = new Node;
NewNode->info = 10;
NewNode->next = ptr->next;
ptr->next = NewNode;
} else {
ptr = ptr->next;
}
You should strongly think about any loop that you write and what loop invariants you want to maintain through the loop as well as what thing is going to change on every loop iteration so that you can have a deterministic end to your loop.
Also, whenever you are dealing with a new type of data structure that you have never worked with before, I recommend drawing out a little diagram with boxes and arrows. This will help you figure out the process which you need to follow to get what you want.
I would start with an initial diagram and then a final diagram showing the picture you want. Then draw a marker that corresponds to the pointer that iterates across your list. Move the marker one time through the loop on each step. Then try to implement the steps you took with the marker in code form.
Here's some example starting diagrams that I drew using Google Docs:
Assume the dotted arrows represent NULL pointers. This gives you three potential starting cases for your linked list.