Do i just have to start again? - data-structures

Put it to me plain and simple please. I was trying to implement a circular doubly linked list with a sentinel node and came up with some higher or lower game that goes backward and forwards and loops through the players. It works fine.... Except I realise i had to have two separate files for the ring module (a .h and a .c) and then a separate main file. The code is long and i have't tidied it up after i realised my mistake as it would be pointless. So im not asking you to read it or check for mistakes or anything. But if you can tell me on a scale of 1-10 how bad the situation is by just skimming over it, i would be very grateful. Just so i can get my head around the scale of what im going to have to do... thanks
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#define PLAYERLIMIT 5
//Doubly linked list implementation
struct Node {
char data[20];
struct Node* next;
struct Node* prev;
};
struct Node* sentinel; //global pointer to the sentinel node
struct Node* head;
struct Node* tail;
// Create sentinel node, originally it just points to itself
struct Node* MakeSentinel () {
struct Node* SentinelNode =
(struct Node*)malloc(sizeof(struct Node));
SentinelNode->next = SentinelNode->next;
SentinelNode->prev = SentinelNode->prev;
return SentinelNode;
}
//Creation of a node takes an int and returns a node
struct Node* GetNewNode (char *x) {
struct Node* newNode =
(struct Node*)malloc(sizeof(struct Node)); //created node in the dynamic memory
strcpy (newNode->data, x); //temp->data is same as (*temp).data
newNode->prev = NULL;
newNode->next = NULL;
return newNode;
}
//Returning a pointer to newly created node, inserts next to sentinel
void InsertAtHead (char *x){
struct Node* newNode = GetNewNode(x);
if (sentinel == NULL) {
sentinel = MakeSentinel();
head = newNode;
sentinel->next = head;
sentinel->prev = head;
head->next = sentinel;
head->prev = sentinel;
return;
}
head->prev = newNode;
newNode->next = head;
newNode->prev = sentinel;
sentinel->prev = newNode;
head = newNode;
}
void PrintHead() {
// printf("Sentinel prev is %s\n", sentinel->prev->data);
struct Node* temp = sentinel->prev;
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
printf("The players in the game are\n\n");
while (temp != sentinel) {
printf ("%s ", temp->data);
temp = temp->next;
}
printf("\n");
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
}
//Removing a name from the linked list
void DeleteEntry (struct Node* del) {
if ((del->next != sentinel) && (del->prev != sentinel)) {
del->next->prev = del->prev;
del->prev->next = del->next;
}
else if (del->next == sentinel) {
del->next->next = del->prev;
del->prev->next = del->next;
}
else if(del->prev == sentinel) {
del->next->prev = del->prev;
del->prev->prev = del->next;
}
// printf("Sentinel prev is now%s\n", sentinel->prev->data);
return;
}
int main(int argc, char *argv[]) {
//Entering all player names into the doubly linked list
printf ("Enter the names of the players. Press Enter after each new player\n");
printf ("Must have 5 Players'.'\n\n");
int i = 1;
char name[20];
while ((i <= PLAYERLIMIT)) {
printf("Player: ");
scanf ("%s", name);
InsertAtHead(name);
i++;
}
PrintHead();
//Starting the Game
//Initialising Variables for the game
int nextCard;
int currentCard;
int score;
char oppositeGuess[20];
int userChoice;
int playGame = 1;
struct Node* CurrentPlayer = head;
struct Node* PlayerBefore;
//Setting up the random cards
int range;
srand(time(NULL));
range = (13 - 1) + 1;
nextCard = rand() % range + 2;
currentCard = rand() % range + 2;
while (playGame == 1) {
//Change current card to past card before creating a new current card
currentCard = nextCard;
//generate a random int for card
nextCard = rand() % range + 2;
if (currentCard < 11) {
printf("\nThe current card is a %d.\n", currentCard);
}
else if (currentCard == 11) {
printf("\nThe current card is a jack.\n");
}
else if (currentCard == 12) {
printf("\nThe current card is a queen.\n");
}
else if (currentCard == 13) {
printf("\nThe current card is a king.\n");
}
else if (currentCard == 14) {
printf("\nThe current card is an ace.\n");
}
printf ("***%s it is your go!***\n", CurrentPlayer->data);
if (CurrentPlayer->prev != sentinel) {
PlayerBefore = CurrentPlayer->prev;
}
else {
PlayerBefore = sentinel->next;
}
// printf("\nThe CurrentPlayer is %s\n", CurrentPlayer->data);
// printf("The PlayerBefore is %s\n\n", PlayerBefore->data);
printf("Will the next card be higher(1) or lower(2)?\n");
scanf("%d", &userChoice);
printf("\n");
printf ("***%s would you like to guess the opposite?***\n", PlayerBefore->data);
scanf("%s", oppositeGuess);
if (strncmp(oppositeGuess, "Yes", 4) == 0) {
if (userChoice == 1) {
if (currentCard < nextCard) {
printf("\nSorry, %s was correct. You are out!\n", CurrentPlayer->data);
// printf ("\n IM GONNA DELETE %s\n", PlayerBefore->data);
DeleteEntry(PlayerBefore);
}
else if (currentCard > nextCard) {
printf ("Congratulations! player %s was wrong and is now out!\n", CurrentPlayer->data);
// printf ("\n IM GONNA DELETE %s\n", CurrentPlayer->data);
DeleteEntry(CurrentPlayer);
}
else if (currentCard == nextCard){
printf("\nCards were equal. Next players turn.\n");
}
}
else if (userChoice == 2) {
if (currentCard < nextCard) {
printf("Congratulations! player %s was wrong and is now out!\n", CurrentPlayer->data);
// printf ("\n IM GONNA DELETE %s\n", CurrentPlayer->data);
DeleteEntry(CurrentPlayer);
}
else if (currentCard > nextCard) {
printf ("\nSorry, %s was correct. You are out!\n", CurrentPlayer->data);
// printf ("\n IM GONNA DELETE %s\n", PlayerBefore->data);
DeleteEntry(PlayerBefore);
}
else if (currentCard == nextCard){
printf("\nCards were equal. Next players turn.\n");
}
}
}
if (strncmp(oppositeGuess, "No", 4) == 0) {
if (userChoice == 1) {
if (currentCard > nextCard) {
printf ("\nSorry you have guessed incorrectly, you are out!\n");
// printf ("\n IM GONNA DELETE %s\n", CurrentPlayer->data);
DeleteEntry(CurrentPlayer);
}
else if (currentCard < nextCard) {
printf("\nCongratualtions you were correct, next players turn.\n");
}
else if (currentCard == nextCard) {
printf("\nThe cards are the same. Next players turn.\n");
}
}
else if (userChoice == 2) {
if (currentCard > nextCard) {
printf ("\nCongratualtions you were correct, next players turn.\n");
}
else if (currentCard < nextCard) {
printf("\nSorry you have guessed incorrectly, you are out!\n");
// printf ("\n IM GONNA DELETE %s\n", CurrentPlayer->data);
DeleteEntry(CurrentPlayer);
}
else if (currentCard == nextCard) {
printf("\nThe cards are the same. Next players turn.\n");
}
}
else {
printf("\nPlease enter a valid choice.\n");
}
}
PrintHead();
if (CurrentPlayer->next != sentinel) {
CurrentPlayer = CurrentPlayer->next;
}
else {
CurrentPlayer = sentinel->prev;
}
if ((CurrentPlayer->next == sentinel) && (CurrentPlayer->prev == sentinel)) {
playGame = 0;
}
}
printf("%s you are the Winner!\n", CurrentPlayer->data);
}

On a scale of 1-10 I think this code is worth saving: you've taken a fairly tedious exercise (making a circular list) and turned it into something fun.
There's no problem with having separate files for different modules, you can include them with a #include command. For example if you put all the linked list stuff in mydllist.c
//Doubly linked list implementation
struct Node {
char data[20];
struct Node* next;
struct Node* prev;
};
struct Node* sentinel; //global pointer to the sentinel node
struct Node* head;
struct Node* tail;
// Create sentinel node, originally it just points to itself
struct Node* MakeSentinel () {
struct Node* SentinelNode = (struct Node*)malloc(sizeof(struct Node));
SentinelNode->next = SentinelNode->next;
SentinelNode->prev = SentinelNode->prev;
return SentinelNode;
}
//Creation of a node takes an int and returns a node
struct Node* GetNewNode (char *x) {
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node)); //created node in the dynamic memory
strcpy (newNode->data, x); //temp->data is same as (*temp).data
newNode->prev = NULL;
newNode->next = NULL;
return newNode;
}
//Returning a pointer to newly created node, inserts next to sentinel
void InsertAtHead (char *x){
struct Node* newNode = GetNewNode(x);
if (sentinel == NULL) {
sentinel = MakeSentinel();
head = newNode;
sentinel->next = head;
sentinel->prev = head;
head->next = sentinel;
head->prev = sentinel;
return;
}
head->prev = newNode;
newNode->next = head;
newNode->prev = sentinel;
sentinel->prev = newNode;
head = newNode;
}
void PrintHead() {
// printf("Sentinel prev is %s\n", sentinel->prev->data);
struct Node* temp = sentinel->prev;
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
printf("The players in the game are\n\n");
while (temp != sentinel) {
printf ("%s ", temp->data);
temp = temp->next;
}
printf("\n");
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
}
//Removing a name from the linked list
void DeleteEntry (struct Node* del) {
if ((del->next != sentinel) && (del->prev != sentinel)) {
del->next->prev = del->prev;
del->prev->next = del->next;
}
else if (del->next == sentinel) {
del->next->next = del->prev;
del->prev->next = del->next;
}
else if(del->prev == sentinel) {
del->next->prev = del->prev;
del->prev->prev = del->next;
}
// printf("Sentinel prev is now%s\n", sentinel->prev->data);
return;
}
You can include it at the top of the dllist_game.c file like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "mydllist.c"
I'd then start by doing some simple refactorings, particularly of your main() function, to make your code easier to understand.
Along with your #define PLAYERLIMIT 5 I'd add a #define NUMBER_OF_CARDS 13 (or whatever the max number of cards is) along with an enum type for boolean values
typedef enum {true, false} bool;
That way when you define range instead of writing:
int range;
srand(time(NULL));
range = (13 - 1) + 1 //n.b. (13 - 1) + 1 = 13 is there some reason you wrote it like this?
You can write
int range = NUMBER_OF_CARDS;
srand(time(NULL));
It always a good idea to initialise variables to a default value: you might forget they're uninitialised and try to use them (which can potentially be bad):
int nextCard = 0;
int currentCard = 0;
int score = 0;
char oppositeGuess[20] = "";
int userChoice = 0 ;
bool playGame = true;
struct Node* CurrentPlayer = head;
struct Node* PreviousPlayer = head->prev;
I'd change the name of the loop counter from i to num_entered_players, so it's easier to see what the variable is for when it's in use:
int num_entered_players = 1;
char name[20];
while ((entered_players <= PLAYERLIMIT)) {
printf("Player: ");
scanf ("%s", name);
InsertAtHead(name);
num_entered_players++;
}
Finally I'd start extracting parts of the big while loop into smaller functions, which describe what's going on. For example the lines:
if (currentCard < 11) {
printf("\nThe current card is a %d.\n", currentCard);
}
else if (currentCard == 11) {
printf("\nThe current card is a jack.\n");
}
else if (currentCard == 12) {
printf("\nThe current card is a queen.\n");
}
else if (currentCard == 13) {
printf("\nThe current card is a king.\n");
}
else if (currentCard == 14) {
printf("\nThe current card is an ace.\n");
}
would become:
void printCurrentCard(int currentCard){
if (currentCard < 11) {
printf("\nThe current card is a %d.\n", currentCard);
}
else if (currentCard == 11) {
printf("\nThe current card is a jack.\n");
}
else if (currentCard == 12) {
printf("\nThe current card is a queen.\n");
}
else if (currentCard == 13) {
printf("\nThe current card is a king.\n");
}
else if (currentCard == 14) {
printf("\nThe current card is an ace.\n");
}
}
and would be called like this:
while (playGame == true) {
//Change current card to past card before creating a new current card
currentCard = nextCard;
//generate a random int for card
nextCard = rand() % range + 2;
printCurrentCard(currentCard);
....
}
etc. So if you change the rules of the game in a particular step, there's only one place you'll need to change the code - and it shouldn't affect the rest of the game.
Once you've done these changes - the logic of your game can go into another pair of .c and .h files and you can call it directly from a separate main()!

Related

Delete smallest node in a linkedlist

I have an assignment to delete the smallest node in a linked list. I wrote the function minelement for this, but it doesn't delete the smallest node. It just deletes all nodes... why does that happen?
My code:
#include <iostream>
#include <string>
using namespace std;
class linkedlist {
private:
struct node {
int item;
node* next;
};
node* first;
node* last;
int count;
public:
linkedlist()
{
first = last = NULL;
count = 0;
}
bool isempty()
{
return (first == NULL);
}
void insertnode(int value) {
node* newNode = new node;
newNode->item = value;
if (count == 0)
{
first = last = newNode;
newNode->next = NULL;
}
else
{
newNode->next = first;
first = newNode;
}
count++;
}
void insertfromLast(int value)
{
node* newNODE = new node;
newNODE->item = value;
if (count == 0)
{
first = last = newNODE;
newNODE->next = NULL;
}
else
{
last->next = newNODE;
newNODE->next = NULL;
last = newNODE;
}
}
void removefirst()
{
node* curr = first;
if (count == 0)
{
cout << "empty list cannot be deleted" << endl;
}
else if (count == 1)
{
delete first;
last = first = NULL;
count--;
}
else
{
first = first->next;
delete curr;
count--;
}
}
void removelast()
{
if (count == 0)
{
cout << "empty list cannot be deleted" << endl;
}
else if (count == 1)
{
delete first;
last = first = NULL;
count--;
}
else
{
node* curr = first->next;
node* prev = first;
while (curr != last)
{
prev = curr;
curr = curr->next;
}
delete curr;
prev->next = NULL;
last = prev;
count--;
}
}
void position(int pos)
{
node* curr = first;
if (count == 0)
{
cout << "Element's positon cannot be found" << endl;
}
else
{
if (pos > count||pos<0)
{
cout << "Out of range so we can't return info of kth element" << endl;
}
else
{
for (int i = 0; i < pos; i++)
{
curr = curr->next;
}
cout << curr->item;
}
count++;
}
}
void remove_existed_element(int element)
{
if (count == 0)
{
cout << "Empty list cannot be deleted" << endl;
}
node* curr = first->next;
node* prev = first;
if (first->item == element)
{
curr = first;
first = first->next;
delete curr;
count--;
}
else
{
while (curr != NULL)
{
if (curr->item == element)
{
break;
}
prev = curr;
curr = curr->next;
}
if (curr == NULL)
{
cout << "Element cannot be found to delete" << endl;
}
else
{
prev->next = curr->next;
delete curr;
count--;
}
}
}
void maxelement()
{
int max = first->item;
node* curr = first->next;
while (curr != NULL)
{
if (curr->item > max)
{
max = curr->item;
}
curr = curr->next;
}
cout << "MAX ELEMENT IS " << max << endl;
count++;
}
void minelement()
{
int min = first->item;
node* curr = first->next;
node* prev = first;
if (isempty())
{
cout << "Empty linked list cannot be deleted" << endl;
}
else if (count == 1)
{
delete first;
count--;
}
else
{
while (curr != NULL)
{
if (min > curr->item)
{
min = curr->item;
}
curr = curr->next;
}
while (curr->item != min) //10 6 5 2//
{
prev = curr;
curr=curr->next;
}
prev->next = curr->next;// prev->next=NULL;
delete (curr);
count--;
}
}
void print()
{
node* curr = first;
while (curr != NULL)
{
cout << curr->item << " ";
curr = curr->next;
}
cout << endl;
}
};
int main()
{
linkedlist l;
l.insertnode(2);
l.insertnode(5);
l.insertnode(6);
l.insertnode(10);
l.minelement();
l.print();
}
Some of the issues:
curr is dereferenced when it is certain that it is NULL:
while (curr != NULL)
{
if (min > curr->item)
{
min = curr->item;
}
curr = curr->next;
}
while (curr->item != min) // <-- curr will be NULL!!!
the function starts with dereferencing first, which is not safe: when the list is empty this will be an invalid reference. So the first thing to do is to check whether the list is empty.
When count == 1, the first member is not set to NULL, ...etc. But since you already have that logic elsewhere, just call removefirst()
It is a pity that you have 2 loops: one to find what is the minimum value, and another to find the node that precedes that minimum value. You should do both in one loop.
Here is the updated function:
void minelement()
{
if (isempty()) // Check this first!
{
cout << "Empty linked list cannot be deleted" << endl;
}
else if (count == 1)
{
removefirst(); // Use your method
}
else
{
// Only access first members when it is safe:
int min = first->item;
node* beforemin = NULL;
node* curr = first->next;
node* prev = first;
while (curr != NULL)
{
if (min > curr->item)
{
min = curr->item;
// Remember where you found it
beforemin = prev;
}
prev = curr; // keep updated
curr = curr->next;
}
if (beforemin == NULL) {
removefirst();
} else if (beforemin->next == NULL) {
removelast();
} else {
curr = beforemin->next;
beforemin->next = curr->next;
delete (curr);
count--;
}
}
}
Unrelated to your question, but you should obviously also update the maxelement function. The position function has some issues too, like:
count++; should not occur there.
pos > count should really be pos >= count, because you seem to use position 0 for the head node, and so the last node has position count-1.
Finally, try to avoid code duplication. There are too many places where you delete and update count. Try to centralise such common code in a method and call it where needed.

Return first unique number in a stream in constant time

How to write a static function that returns first unique number in a stream of numbers if current number is a terminating number (e.g. zero). Otherwise, it should return zero.
static int firstUnique(int number);
Time complexity should be O(1). What data structure should I use?
Use map and doubly linkedlist :
#include <iostream>
#include <unordered_map>
#include <vector>
using namespace std;
const int TERMINATOR = 0;
struct Node {
int data;
Node* next;
Node* prev;
};
int firstUnique(int number){
static unordered_map<int, Node*> numToIsUnique;
static Node* head = nullptr; // first unique
static Node* tail = nullptr; // last unique
if (number != TERMINATOR){
Node* newNode = new Node{number, nullptr, nullptr};
if (numToIsUnique.insert(make_pair(number, newNode)).second == false) {
// insert fails => number is not unique
// Need to delete from LinkedList
Node* nodeToDelete = numToIsUnique[number];
if (nodeToDelete != nullptr){ // delete only once
if (head == nodeToDelete && tail == nodeToDelete){
// head == tail - one node
head = nullptr;
tail = nullptr;
}
else if (head == nodeToDelete){
// head to delete
head = head->next;
head->prev = nullptr;
}
else if (tail == nodeToDelete){
// tail to delete
tail = tail->prev;
tail->next = nullptr;
}
else {
// delete node in the middle
nodeToDelete->prev->next = nodeToDelete->next;
nodeToDelete->next->prev = nodeToDelete->prev;
}
delete nodeToDelete;
numToIsUnique[number] = nullptr;
}
}
else {
// number is new => need to append at the end of link list (last unique)
if (head == nullptr){
// list is empty
head = newNode;
tail = head;
}
else if (head == tail){
// list has one node
tail = newNode;
newNode->prev = head;
head->next = tail;
}
else {
// list has more than one node
newNode->prev = tail;
tail->next = newNode;
tail = newNode;
}
}
return TERMINATOR;
}
else {
// Output head
if (head == nullptr){
return TERMINATOR;
}
else {
return head->data;
}
}
}

Find the Error or memory leak

I was writing LinkedList Program in C++
Here is the Code. Find the Error and Memory Leak or anything else.
I want to write a perfect code.
#ifndef LEARN_REVERSELINKLIST_H
#define LEARN_REVERSELINKLIST_H
#include <string>
#include <utility>
#include <iostream>
#include <boost/assert.hpp>
class ReverseLinkList {
private:
struct Node {
std::string string;
Node *Previous{};
Node *Next{};
};
Node *head;
Node *tail;
int count;
public:
ReverseLinkList();
~ReverseLinkList();
void insert(std::string string);
void insertAt(std::string string, int position);
void iterator() const;
void reverseIterator() const;
void remove(const std::string &string);
void removeAt(int position);
int size() const;
Node *getHead() const;
Node *getTail() const;
};
#endif //LEARN_REVERSELINKLIST_H
and Here is the CC File
#include "ReverseLinkList.h"
ReverseLinkList::~ReverseLinkList() {
if (count != 0) {
Node *temp = head;
while (temp != tail->Next) {
delete temp->Previous;
temp = temp->Next;
}
tail = nullptr;
head = nullptr;
}
}
ReverseLinkList::ReverseLinkList()
: head(nullptr), tail(nullptr), count(0) {
}
void ReverseLinkList::iterator() const {
BOOST_ASSERT_MSG(count != 0, "List is empty");
Node *temp;
temp = head;
while (temp != tail->Next) {
std::cout << temp->string << std::endl;
temp = temp->Next;
}
}
void ReverseLinkList::reverseIterator() const {
BOOST_ASSERT_MSG(count != 0, "List is empty");
Node *temp;
temp = tail;
while (temp != head->Previous) {
std::cout << temp->string << std::endl;
temp = temp->Previous;
}
}
void ReverseLinkList::insert(std::string string) {
auto *newNode = new Node;
newNode->string = std::move(string);
count++;
if (head == nullptr && tail == nullptr) {
newNode->Previous = nullptr;
newNode->Next = nullptr;
head = newNode;
tail = newNode;
} else {
tail->Next = newNode;
newNode->Next = nullptr;
newNode->Previous = tail;
tail = newNode;
}
}
int ReverseLinkList::size() const {
return count;
}
void ReverseLinkList::remove(const std::string &string) {
BOOST_ASSERT_MSG(count != 0, "List is empty");
if (count == 1) {
if (head->string == string) {
delete head;
head = nullptr;
tail = nullptr;
}
count--;
return;
}
if (head->string == string) {
Node *temp;
temp = head->Next;
delete head;
head = temp;
head->Previous = nullptr;
count--;
return;
}
if (tail->string == string) {
Node *temp;
temp = tail->Previous;
delete tail;
tail = temp;
temp->Next = nullptr;
count--;
return;
}
Node *temp;
temp = head;
bool verbose = true;
while (temp != tail->Next) {
if (temp->string == string) {
verbose = false;
break;
}
temp = temp->Next;
}
if (verbose) {
std::cerr << "Node not present" << std::endl;
return;
}
Node *previous, *next;
previous = temp->Previous;
next = temp->Next;
delete temp;
previous->Next = next;
next->Previous = previous;
count--;
}
void ReverseLinkList::insertAt(std::string string, int position) {
if (position > count)
return;
if (position == 0) {
if (head == nullptr) {
insert(string);
return;
}
auto *newNode = new Node;
newNode->string = string;
newNode->Previous = nullptr;
head->Previous = newNode;
newNode->Next = head;
head = newNode;
count++;
return;
}
if (position == count - 1) {
insert(string);
return;
}
Node *temp;
temp = head;
while (position != 0) {
temp = temp->Next;
position--;
}
Node *next;
next = temp->Next;
auto *newNode = new Node;
newNode->string = string;
temp->Next = newNode;
newNode->Previous = temp;
newNode->Next = next;
next->Previous = newNode;
count++;
}
ReverseLinkList::Node *ReverseLinkList::getHead() const {
return head;
}
ReverseLinkList::Node *ReverseLinkList::getTail() const {
return tail;
}
void ReverseLinkList::removeAt(int position) {
BOOST_ASSERT_MSG(count != 0, "List is empty");
if (position > count)
return;
Node *temp;
if (count == 1) {
delete head;
head = nullptr;
tail = nullptr;
count--;
return;
}
if (position == 0) {
temp = head->Next;
delete head;
head = temp;
head->Previous = nullptr;
count--;
return;
}
if (position == count) {
temp = tail->Previous;
delete tail;
tail = temp;
tail->Next = nullptr;
count--;
return;
}
temp = head;
while (position != 0) {
temp = temp->Next;
position--;
}
Node *previous;
Node *next;
previous = temp->Previous;
next = temp->Next;
delete temp;
previous->Next = next;
next->Previous = previous;
count--;
}
I would like to have some suggestion how can I write better code and Implement it. If you have some functions you would like to add please do post.
My next move is to make this code using templates

How to store an array of LinkedList heads in C++?

Given a binary tree, I'm trying to make a linked list of elements for each depth. That makes D lists for depth D. I'm doing a non-recursive implementation and using level order traversal in my C++ code. Though I don't see any error while compilation, I know that my heads are not storing in the array of pointers. Please have a look at my code. Any help or suggestion would be great since I'm new to data structures. Thanks!
#include <iostream>
#include <queue>
using namespace std;
struct BTnode
{
int data;
BTnode* left;
BTnode* right;
};
struct LLnode
{
int data;
LLnode* next;
};
BTnode* newNode(int data)
{
BTnode* node = new BTnode;
node->data = data;
node->left = NULL;
node->right = NULL;
return node;
}
void MakeLL(LLnode* &head, int data)
{
LLnode* temp = new LLnode;
temp->data = data;
if (head == NULL)
{
head = temp;
temp->next = NULL;
}
else
{
temp->next = head;
head = temp;
}
}
LLnode** LevelElementsLinkedlist(BTnode* &root)
{
if (root == NULL)
return NULL;
queue<BTnode*>nodeQ;
nodeQ.push(root);
int level = 0;
LLnode **arr;
while(1)
{
int count = nodeQ.size();
if (count == 0)
break;
LLnode* head = NULL;
arr[level] = head;
level ++;
while (count > 0)
{
BTnode* node = nodeQ.front();
MakeLL(head,node->data);
nodeQ.pop();
if (node->left)
nodeQ.push(node->left);
if (node->right)
nodeQ.push(node->right);
count--;
}
}
return arr;
}
void printLL(LLnode* head)
{
if (head == NULL)
return;
LLnode* temp = head;
while (temp != NULL)
{
cout << temp->data << " ";
temp = temp->next;
}
}
int main()
{
BTnode* root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(40);
root->left->right = newNode(5);
root->right->left = newNode(60);
root->right->right = newNode(7);
root->left->left->left = newNode(8);
root->left->left->right = newNode(9);
root->left->right->left = newNode(10);
root->left->right->right = newNode(11);
root->right->left->left = newNode(12);
root->right->left->right = newNode(13);
root->right->right->left = newNode(14);
root->right->right->right = newNode(15);
LLnode** arr = LevelElementsLinkedlist(root);
int n = sizeof(arr)/sizeof(arr[0]);
cout << n;
for (int i = 0; i < n; i++)
{
printLL(arr[i]);
cout << endl;
}
cout << endl;
return 0;
}
There are a few problem that I noticed in your code.
In the function LevelElementsLinkedlist, you are not allocating space for arr. It should be LLnode *arr = new LLnode *[100].
Check the line where you have written the following:
LLnode* head = NULL;
arr[level] = head;
You are assigning NULL to head and then adding it to the array. Your whole array will contain nothing else but NULLs.
Try fixing these issues and try executing your code again.

Finding and removing the last occurrence of an element in a (singly) linked list with only one traversal

Is it possible to find the last occurrence of an element (for example, an integer) and remove this node with only one (forward) traversal through the list?
Yes.
Simply remember the previous entry every time you find the value you're searching for on the traversal. When the traversal is complete, the last entry remembered will have a link to the entry to be removed, and that is sufficient to do the removal.
public void DeleteLastOccurenceOfKey(Node head, int key)
{
Node current=head;
Node prev=null;
Node temp=null;
while(current!=null)
{
if(current.next!=null && current.next.data==key)
{
prev=current;
temp=current.next;
}
current=current.next;
}
prev.next=temp.next;
}
DeleteLastOccurenceOfKey(head,25);
I/P:5 10 15 25 35 25 40
O/P:5 10 15 25 35 40
/*
* Delete last occurrence of an item from linked list
* Given a liked list and a key to be deleted. Delete last occurrence of key
* from linked. The list may have duplicates.
*
* Examples:
*
* Input: 1->2->3->5->2->10, key = 2`enter code here`
* Output: 1->2->3->5->10
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct list_ list;
struct list_ {
int d;
list *next;
};
void insert (list **head, int d) {
list *tmp = (list *)malloc(sizeof(list));
assert(tmp);
tmp->d = d;
tmp->next = *head;
*head = tmp;
}
void printL (list *p) {
while (p) {
printf (" %d ", p->d);
p = p->next;
}
printf ("\n");
}
void deletlastOccurence (list **head, int d) {
list *cur = *head;
list *prev = NULL;
list *match = NULL;
if (cur == NULL) {
printf ("list is empty\n");
return;
}
/*
* Special case when there only ONE NODE
* in the LIST
*/
if (cur->next == NULL) {
if (cur->d == d) {
printf ("Deleted one node %d\n", cur->d);
free(cur);
*head = NULL;
} else {
printf(" No match\n");
}
return;
}
/*
* Keep track of previous node
*/
while (cur && cur->next) {
if (cur->next->d == d) {
prev = cur;
match = cur->next;
}
cur = cur->next;
}
if (prev){
prev->next = match->next;
printf ("Delete %d\n", match->d);
free (match);
} else {
/*
* Special case when the last node is
* on the head itself
*/
if ((*head)->d == d) {
cur = *head;
*head = cur->next;
printf("element is at head Delete %d\n", cur->d);
free (cur);
} else {
printf ("No match\n");
}
}
printL(*head);
}
int main (int argc , char *argv) {
list *h = NULL;
insert(&h, 1);
insert(&h, 2);
insert(&h, 3);
insert(&h, 4);
insert(&h, 5);
insert(&h, 2);
insert(&h, 1);
insert(&h, 6);
printL(h);
deletlastOccurence(&h, 6);
deletlastOccurence(&h, 2);
}
public void deleteLastOccurence(int value) {
Element cur = this.head;
Element prev = null;
Element tmp = null;
if(this.head == null)
return;
if(this.head.data == value) {
this.head = null;
return;
}
while(cur != null) {
if(cur.next != null && cur.next.data == value) {
prev = cur;
tmp = cur.next;
}
cur = cur.next;
}
prev.next = tmp.next;
}

Resources