Circular Traversal of a Linked List - c++

So I'm having some trouble with one of my functions. The program (in C++) plays a game, and there are so many players sitting at the table. Every time my play function is called, it should display to the console a player in the game. Every time it is called it should display the players in sequence. After it hits the last player it will start back at the beginning of the list/table.
void CircleList::play()
LinkedListOfPlayersNode *p=(*pFront).pNext;
if (p->pData!=NULL)
{
cout<<p->pData->getName()+" takes a turn\n";
pLastPlayer = pLastPlayer->pNext;
}
else
{
cout<<"There are no players. Please ADD a player.\n";
}
}
So lets say that that we add A, B, and C. When you use the PLAY command, C should take a turn, then B then A. As of right now with the above code, it will display that C Takes a Turn, however, it crashes right after that.
So what is wrong with my code? Is there a better way to write this?

I'm pretty sure you want that traversal to look something like this:
LinkedListOfPlayersNode *p = pNextPlayer ? pNextPlayer : pFront;
if (p && p->pData) // not sure why pData is also dynamic. look into that.
{
cout<<p->pData->getName()+" takes a turn\n";
pNextPlayer = p->pNext;
}
else
{
cout<<"There are no players. Please ADD a player.\n";
}
Each time a player's turn comes up, they take it, and the next player is that player's next pointer. When your last player at the table takes a turn, p->pNext will be null, and the next invoke will reset to the head of the list.
At least thats where I think you're trying to get. Prime this with either pNextPlayer being set to pFront or NULL; makes no difference.

Lets say you initially define pnext = NULL in while creating nodes.
So according to your code;
if (p->pData!=NULL)
{
cout<<p->pData->getName()+" takes a turn\n";
pLastPlayer = pLastPlayer->pNext;
}
else
{
cout<<"There are no players. Please ADD a player.\n";
}
There are 2 scenarios according to my assumptions:
1. p and pLastPlayer are the same ... so after the list is over. p will be equal to NULL, your code will crash as it tries to de-reference p->pData.
2. p and pLastPlayer are different ... So after the list pLastPlayer ends, the code will crash at pLastPlayer = pLastPlayer -> pNext(); as you are probably de-referencing garbage or NULL value;
You need to check for NULL pointers at some point, either in p -> pData != NULL or pLastPlayer = pLastPlayer -> pNext();

You are in C++, you are better off with a std::list than writing your own implementation.
Something's bugging me: Why are you starting your loop with "p = (*pFront).pNext" instead of starting it straight with "p = pFront"?
How are you adding your nodes to your list? You should be echo-ing "A takes a turn" before "C takes a turn".
If you are indeed adding to the front of your list (and your list is doubly-linked), you should call pPrevious instead of pNext.

Related

Recursive function removing all instances of a character in a linked list

I wrote a recursive to remove nodes with a specific data value, however it is not working correctly.
Node * removeAll(Node *top, char c){
if(top == NULL)
return NULL;
Node *newTop;
if(top->data == c){
newTop = top->next;
delete top;
}else{
newTop = top;
}
newTop->next = removeAll(newTop->next,c);
return newTop;
}
The linked list provided to the function contains the values h e l l o
I expected the outputted list to contain the values h e o, but instead it has the values h e l o
I'll answer this as a tutorial because nearly everyone struggles a bit when learning how to think recursively.
Note that because it uses a while loop, #Edward's answer isn't a fully recursive form.
When you're learning, it invariably helps to write out a recursive description of the answer in human language first. Starting with code draws focus away from thinking about the algorithm and toward unimportant details like syntax and pointer semantics. In English,
A list of the form [HEAD, rest_of_list] with character C removed is equal to rest_of_list with character C removed and HEAD optionally pre-pended to it. Whether to prepend HEAD or not depends on whether it's equal to C.
Here HEAD is a single character, and rest_of_list is itself a list.
The recursive part is removing C from rest_of_list. Note that the recursion is occurring on a string one character shorter than the input. That's good! It means that the algorithm is making progress from one recursive call to the next.
We'll also need to describe a "base case" where the recursion stops. Here since the list is getting shorter from one call to the next, it's logical to try the empty list. In English,
When the input list is empty, it can't contain C, so return the empty list.
So we're ready to write code. First the base case. Your implementation is fine. A NULL pointer is the empty list in the usual C list implementation.
Node *removeAll(Node *list, char c) {
// Base case.
if (list == NULL) return NULL;
// Recursive case.
// TODO: Complete me.
}
For the recursive case, HEAD as we wrote in English is list->data in C. And rest_of_list is list->next. So go ahead and write that:
// Recursive case.
char head = list->data;
Node *rest = list->next;
The recursive case itself has 2 cases. If head is c, then we just return rest with c removed.
if (c == head) return removeAll(rest, c);
The remaining case is where head is not equal to c. Here there's a choice. You need a node to hold c. You can either re-use the one that currently holds it, which means you're changing the original list. Or you can allocate a new node, which means the original list remains intact. In real applications, this decision can be extremely important. Let's say you want to keep the original list intact. Prepending is accomplished with
return allocateNewNode(head, removeAll(rest, c));
Here allocateNewNode gets fresh memory for the node that's not being used for some other list. For example, it could call malloc.
On the other hand, if you want to change the input list (the term mutate is pretty common), then modify the first node in list.
list->next = removeAll(rest, c);
return list;
All together, the mutating case is:
Node *removeAll(Node *list, char c) {
// Base case: on empty list, return empty list.
if (list == NULL) return NULL;
// Recursive cases. Extract head value and rest of list.
char head = list->data;
Node *rest = list->next;
// If head is C, return rest with C removed.
if (c == head) return removeAll(rest, c);
// Otherwise prepend C to rest with C removed by mutating the first list node,
// which already contains head.
list->next = removeAll(rest, c);
return list;
}
I hope this is helpful to you and others trying to get the hang of recursive thinking.
Change this:
if(top->data == c){
newTop = top->next;
delete top;
}else{
newTop = top;
}
to this:
while(top && top->data == c){
newTop = top->next;
delete top;
top = newTop;
}
newTop = top;
That way successive elements which contain the target value will all be deleted before moving to the next element.
As an aside, this function might use less memory and be faster if it were written iteratively rather than recursively.

How to remove duplicates from linked list which repeats double number of times?

I've been trying to create own linked list class on C++. My task is remove all nodes which data repeats double number of times in list and store only one node if data repeats odd number of times. I've written function removeDuplicates(), but my program crashes when i try to use the function. Implementation here:
void LinkedList::removeDuplicates(){
Node *ptr1, *ptr2, *dup, *toDel;
int counter = 1;
ptr1 = top;
while(ptr1 != NULL && ptr1->next != NULL){
ptr2 = ptr1;
while(ptr2->next != NULL){
if(ptr1->name == ptr2->next->name){
dup = ptr2->next;
ptr2->next = ptr2->next->next;
delete dup;
counter++;
} else {
ptr2 = ptr2->next;
}
}
if(counter % 2 == 0){
toDel = ptr1;
ptr1->next = ptr1->next->next;
ptr1 = ptr1->next;
delete toDel;
}else{
ptr1 = ptr1->next;
}
}
}
Firstly: Please learn to use a debugger. Knowing the exact line where it crashes and looking at the variables and pointers at runtime, and stepping through the code will save you from asking these: "I wrote some code, it's broke, fix it please." 'questions'.
If gdb is unwieldy for you, use visual studio or something.
As Some programmer dude suggested: learn how to debug your code.
Regarding your actual problem:
After your inner loop.
ptr1->next = ptr1->next->next;
is not checked if (ptr1->next == NULL). Thus accessing ptr1->next->next will result in an access violation.
While that check is in the outer while loop condition, the inner while loop may delete and unlink the object from your list.
I'm also fairly certain that you want to reset your counter somewhere in the outer loop, probably right at the start. as it is now, it doesn't count the number of occurences of any one ptr2->name
Also you should initialize variables right in the declaration, it's just good style and may avoid further hassle.
It is also a good idea to set your pointers to NULL after deleting, so you DO get a nice null pointer exception instead of it randomly 'working' or crashing.

Program crashes when opening and processing input files

I'm currently working on a program, and I'm running into a small issue. It's reading data from a text file, and when the numbers are in ascending order, it runs fine, but when I have numbers in a random order, it crashes. I've debugged it and traced it to this if statement, but I can't figure out what the heck I did wrong.
if(tempNode != NULL)
{
struct doublyLinkNode* temp = new doublyLinkNode;
temp->nextNode = tempNode;
temp->previousNode = tempNode->previousNode;
temp->nodeValue = noToInsert;
tempNode->previousNode->nextNode = temp;
tempNode->previousNode= temp;
list->count++;
return true;
} // end if
The list building crashes when a new number to be added precedes the current top of the list. I think the pointer is attempting to write to an invalid pointer.
Your error is to be expected. You want to insert nodes before the current one (tempNode),
and you´re using tempNode->previousNode in the code.
If tempNode happens to be the first node, what´s tempNode->previousNode? Right, NULL
(unless you have a circular list, but then you wouldn´t have this problem). That means
tempNode->previousNode->nextNode = temp; will crash.
As solution to this part, just make an if:
if(tempNode->previousNode != NULL) tempNode->previousNode->nextNode = temp;
(assuming that everything is initialized properly). Depending on how you implemented the list, you may need to change the information what the first node is, too.

Low Memory Shortest Path Algorithm

I have a global unique path table which can be thought of as a directed un-weighted graph. Each node represents either a piece of physical hardware which is being controlled, or a unique location in the system. The table contains the following for each node:
A unique path ID (int)
Type of component (char - 'A' or 'L')
String which contains a comma separated list of path ID's which that node is connected to (char[])
I need to create a function which given a starting and ending node, finds the shortest path between the two nodes. Normally this is a pretty simple problem, but here is the issue I am having. I have a very limited amount of memory/resources, so I cannot use any dynamic memory allocation (ie a queue/linked list). It would also be nice if it wasn't recursive (but it wouldn't be too big of an issue if it was as the table/graph itself if really small. Currently it has 26 nodes, 8 of which will never be hit. At worst case there would be about 40 nodes total).
I started putting something together, but it doesn't always find the shortest path. The pseudo code is below:
bool shortestPath(int start, int end)
if start == end
if pathTable[start].nodeType == 'A'
Turn on part
end if
return true
else
mark the current node
bool val
for each node in connectedNodes
if node is not marked
val = shortestPath(node.PathID, end)
end if
end for
if val == true
if pathTable[start].nodeType == 'A'
turn on part
end if
return true
end if
end if
return false
end function
Anyone have any ideas how to either fix this code, or know something else that I could use to make it work?
----------------- EDIT -----------------
Taking Aasmund's advice, I looked into implementing a Breadth First Search. Below I have some c# code which I quickly threw together using some pseudo code I found online.
pseudo code found online:
Input: A graph G and a root v of G
procedure BFS(G,v):
create a queue Q
enqueue v onto Q
mark v
while Q is not empty:
t ← Q.dequeue()
if t is what we are looking for:
return t
for all edges e in G.adjacentEdges(t) do
u ← G.adjacentVertex(t,e)
if u is not marked:
mark u
enqueue u onto Q
return none
C# code which I wrote using this code:
public static bool newCheckPath(int source, int dest)
{
Queue<PathRecord> Q = new Queue<PathRecord>();
Q.Enqueue(pathTable[source]);
pathTable[source].markVisited();
while (Q.Count != 0)
{
PathRecord t = Q.Dequeue();
if (t.pathID == pathTable[dest].pathID)
{
return true;
}
else
{
string connectedPaths = pathTable[t.pathID].connectedPathID;
for (int x = 0; x < connectedPaths.Length && connectedPaths != "00"; x = x + 3)
{
int nextNode = Convert.ToInt32(connectedPaths.Substring(x, 2));
PathRecord u = pathTable[nextNode];
if (!u.wasVisited())
{
u.markVisited();
Q.Enqueue(u);
}
}
}
}
return false;
}
This code runs just fine, however, it only tells me if a path exists. That doesn't really work for me. Ideally what I would like to do is in the block "if (t.pathID == pathTable[dest].pathID)" I would like to have either a list or a way to see what nodes I had to pass through to get from the source and destination, such that I can process those nodes there, rather than returning a list to process elsewhere. Any ideas on how i could make that change?
The most effective solution, if you're willing to use static memory allocation (or automatic, as I seem to recall that the C++ term is), is to declare a fixed-size int array (of size 41, if you're absolutely certain that the number of nodes will never exceed 40). By using two indices to indicate the start and end of the queue, you can use this array as a ring buffer, which can act as the queue in a breadth-first search.
Alternatively: Since the number of nodes is so small, Bellman-Ford may be fast enough. The algorithm is simple to implement, does not use recursion, and the required extra memory is only a distance (int, or even byte in your case) and a predecessor id (int) per node. The running time is O(VE), alternatively O(V^3), where V is the number of nodes and E is the number of edges.

For Looping Link List using Templates

Having used the various search engines (and the wonderful stackoverflow database), I have found some similar situations, but they are either far more complex, or not nearly as complex as what I'm trying to accomplish.
C++ List Looping
Link Error Using Templates
C++:Linked List Ordering
Pointer Address Does Not Change In A Link List
I'm trying to work with Link List and Node templates to store and print non-standard class objects (in this case, a collection of categorized contacts). Particularly, I want to print multiple objects that have the same category, out of a bunch of objects with different categories. When printing by category, I compare an sub-object tmpCategory (= "business") with the category part of a categorized contact.
But how to extract this data for comparison in int main()?
Here's what I'm thinking. I create a GetItem member function in LinkList.tem This would initialize the pointer cursor and then run a For loop until the function input matches the iteration number. At which point, GetItem returns object Type using (cursor -> data).
template <class Type>
Type LinkList<Type>::GetItem(int itemNumber) const
{
Node<Type>* cursor = NULL;
for(cursor = first;
cursor != NULL;
cursor = (cursor -> next))
{
for(int i = 0; i < used; i++)
{
if(itemNumber == i)
{
return(cursor -> data);
}
}
}
}
Here's where int main() comes in. I set my comparison object tmpCategory to a certain value (in this case, "Business"). Then, I run a For loop that iterates for cycles equal to the number of Nodes I have (as determined by a function GetUsed()). Inside that loop, I call GetItem, using the current iteration number. Theoretically, this would let the int main loop return the corresponding Node from LinkList.tem. From there, I call the category from the object inside that Node's data (which currently works), which would be compared with tmpCategory. If there's a match, the loop will print out the entire Node's data object.
tmpCategory = "Business";
for(int i = 0; i < myCategorizedContact.GetUsed(); i++)
{
if(myCategorizedContact.GetItem(i).getCategory() == tmpCategory)
cout << myCategorizedContact.GetItem(i);
}
The problem is that the currently setup (while it does run), it returns nothing at all. Upon further testing ( cout << myCategorizedContact.GetItem(i).getCategory() ), I found that it's just printing out the category of the first Node over and over again. I want the overall scheme to evaluate for every Node and print out matching data, not just spit out the same Node.
Any ideas/suggestions are greatly appreciated.
Please look at this very carefully:
template <class Type>
Type LinkList<Type>::GetItem(int itemNumber) const
{
Node<Type>* cursor = NULL;
// loop over all items in the linked list
for(cursor = first;
cursor != NULL;
cursor = (cursor -> next))
{
// for each item in the linked list, run a for-loop
// counter from 0 to (used-1).
for(int i = 0; i < used; i++)
{
// if the passed in itemNumber matches 'i' anytime
// before we reach the end of the for-loop, return
// whatever the current cursor is.
if(itemNumber == i)
{
return(cursor -> data);
}
}
}
}
You're not walking the cursor down the list itemNumber times. The very first item cursor references will kick off the inner-for-loop. The moment that loop index reaches itemNumber you return. You never advance your cursor if the linked list has at least itemNumber items in the list.. In fact, the two of them (cursor and itemNumber) are entirely unrelated in your implementation of this function. And to really add irony, since used and cursor are entirely unrelated, if used is ever less than itemNumber, it will ALWAYS be so, since used doesn't change when cursor advances through the outer loop. Thus cursor eventually becomes NULL and the results of this function are undefined (no return value). In summary, as written you will always either return the first item (if itemNumber < used), or undefined behavior since you have no return value.
I believe you need something like the following instead:
template< class Type >
Type LinkList<Type>::GetItem(int itemNumber) const
{
const Node<Type>* cursor = first;
while (cursor && itemNumber-- > 0)
cursor = cursor->next;
if (cursor)
return cursor->data;
// note: this is here because you're definition is to return
// an item COPY. This case would be better off returning a
// `const Type*` instead, which would at least allow you to
// communicate to the caller that there was no item at the
// proposed index (because the list is undersized) and return
// NULL, which the caller could check.
return Type();
}