Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have a task where I need to design and implement a class template using singly-linked list:
template <typename Key, typename Info> class Sequence { // ... // implemented using a singly-linked list }
The second part of the task comes after the main implementation, which is to create a function 'shuffle' To test flexibility of the class template above.
template <typename Key, typename Info> Sequence<Key, Info> shuffle ( const Sequence<Key, Info> & source1, int startIndex1, int length1, const Sequence<Key, Info> & source2, int startIndex2, int length2)
The function template shuffle should produce a sequence from two input sequences by interleaving subsequences of lengths length1 and length2 respectively. The subsequences should start at positions startIndex1 and startIndex2 respectively and continue till the ends of source sequences.
Let’s have an example with sequences, where keys are presented with colours distinguishing the source sequences
RESULT = shuffle ( source1, 3, 3, source2, 1, 2)
I have so far implemented everything that is necessary for a class template using singly-linked list.
The only part I need help implementing is the shuffle function described above. here's my code so far:
#include <iostream>
using namespace std;
template < typename Key, typename Info > class Sequence;
template < typename Key, typename Info >
Sequence <Key, Info> operator+ (const Sequence < Key, Info > &a,
const Sequence < Key, Info > &b);
template < typename Key, typename Info > class Sequence
{
private:
struct Node
{
Key ID;
Info information;
Node *next;
};
Node *head; // it's a singly linked list, but requires both head & tail in order to use the insert before& after function
Node *tail;
int numberOfNode;
void removeAll () //because c++ does not remove anything automatically, needs to remove all
{
if (head == NULL)
return;
Node *NodeToDelete = head;
while (NodeToDelete != NULL)
{
head = head->next;
delete[]NodeToDelete;
delete NodeToDelete;
NodeToDelete = head; //now the first node of the list is gone, nodeToDelete is the second node
}
tail = NULL;
numberOfNode = 0;
};
void copyAll (const Sequence < Key, Info > &s)
{
head = NULL;
tail = NULL;
numberOfNode = 0;
if (s.head == NULL)
return;
Node *NodeToCopy = s.head;
while (NodeToCopy)
{
push_back (NodeToCopy->ID, NodeToCopy->information);
NodeToCopy = NodeToCopy->next;
}
};
public:
Sequence ()
{
head = NULL;
tail = NULL;
numberOfNode = 0;
}
~Sequence ()
{
removeAll ();
}
Sequence (const Sequence < Key, Info > &s)
{
copyAll (s);
}
Sequence & operator= (const Sequence < Key, Info > &s)
{
if (this == &s)
return *this;
removeAll ();
copyAll (s);
return *this;
}
bool operator== (const Sequence < Key, Info > &s) const
{
if (size() != s.size())
return false;
Node *NodeToCompare = s.head;
Node *comparedNode = head;
while (NodeToCompare != NULL)
{
if (comparedNode->ID == NodeToCompare->ID)
{
NodeToCompare = NodeToCompare->next;
comparedNode = comparedNode->next;
}
else
return false;
}
return true;
}
bool operator != (const Sequence < Key, Info > &s) const
{
//writing the interior of the function simply as a return value
//in the end, true& false values are outputted as 1/0, bool returns 1/0
return !(*this == s);
}
//+= operator processes and returns everything to the object itself
Sequence < Key, Info > &operator += (const Sequence < Key, Info > &s)
{
if (s.empty ())
return *this;
if (this == &s)
{
*this = *this + s;
return *this;
}
Node *NodeToCopy = s.head;
while (NodeToCopy != NULL)
{
push_back (NodeToCopy->ID, NodeToCopy->information);
NodeToCopy = NodeToCopy->next;
}
return *this;
}
//operator + can add multiple things at the same time. Doesn't necessarily need to obtain a sum
Sequence < Key, Info > &operator + (const Sequence < Key, Info > &a)
{
Node *temp = a.head;
while (temp != NULL)
{
push_back (temp->ID, temp->information);
temp = temp->next;
}
return *this;
}
void insertAfter (const Key &location, const Key & newID,
const Info & newInfo)
{
Node *NodeToAdd = new Node (newID, newInfo, NULL);
if (head == NULL)
{
head = NodeToAdd;
tail = head;
numberOfNode++;
return;
}
//We get the position of head from constructor, once we add sth there
Node *current = head; // looking for position location we will place new created Node
while (current->next != NULL && current->ID != location)
current = current->next;
//Connecting between the new node, and the second half of the node first, so that when splitting the link, the second half won't be lost
NodeToAdd->next = current->next;
//Now, disconnecting the link between the current node to the second half of the link, so the new node can be the only link that connect them 2.
current->next = NodeToAdd; // if we want to add to the end of the list we will need to set tail pointer correctly
if (!NodeToAdd->next)
tail = NodeToAdd;
numberOfNode++;
}
void insertBefore (const Key & location, const Key & newID,
const Info & newInfo)
{
Node *NodeToAdd = new Node (newID, newInfo, NULL);
Node *current = head;
Node *previous = NULL; // looking for position location we will place new created Node
while (current != NULL && current->ID != location)
{
previous = current;
current = current->next;
} // we want to add at the beginning or we want to add first Node
if (!previous)
{
NodeToAdd->next = head;
head = NodeToAdd;
if (!tail)
tail = head;
}
else
{
NodeToAdd->next = previous->next;
previous->next = NodeToAdd; // if we want to add to the end of the list we will need to set tail pointer correctly
if (!NodeToAdd->next)
tail = NodeToAdd;
}
numberOfNode++;
}
//add Node in the end of the list
void push_back (const Key & newID, const Info & newInfo)
{
Node *NodeToAdd = new Node ();
NodeToAdd->ID = newID;
NodeToAdd->information = newInfo;
NodeToAdd->next = NULL;
if (head == NULL)
{
head = NodeToAdd;
tail = head;
}
else
{
tail->next = NodeToAdd;
tail = tail->next;
}
numberOfNode++;
}
//add Node in front of the list
void push_front (const Key & newID, const Info & newInfo)
{
Node *NodeToAdd = new Node (newID, newInfo, head);
if (head == NULL)
{
head = NodeToAdd;
tail = head;
}
else
head = NodeToAdd;
numberOfNode++;
}
bool remove (const Key & location)
{
if (head == NULL)
return false;
Node *NodeToDelete = head;
Node *previous = NULL; // looking for position of Node to be deleted
while (NodeToDelete != NULL && NodeToDelete->ID != location)
{
previous = NodeToDelete;
NodeToDelete = NodeToDelete->next;
} // if Node is found
if (NodeToDelete)
{ // if we want to delete the first Node
if (!previous)
{
head = head->next;
delete NodeToDelete;
numberOfNode--;
if (size () == 0)
tail = NULL;
}
else
{
previous->next = NodeToDelete->next;
delete NodeToDelete;
numberOfNode--; // if we have deleted tail Node
if (!previous->next)
tail = previous;
}
return true;
} // Node not found
else
return false;
}
bool positionKey (int place) const
{
//head isn't empty, and the place is a valid value
if (head != NULL && place >= 0)
{
Node *temp = head;
int i = 0;
while (i < place && temp != NULL)
{
temp = temp->next;
++i;
}
if (temp != NULL)
return true;
}
return false;
}
Key & positionKeyAt (int place) const
{
Node *temp = head;
int i = 0;
while (i < place && temp != NULL)
{
temp = temp->next;
++i;
}
return temp->ID;
}
bool positionInfo (int place) const
{
if (head != NULL && place >= 0)
{
Node *temp = head;
int i = 0;
while (i < place && temp != NULL)
{
temp = temp->next;
++i;
}
if (temp != NULL)
return true;
}
return false;
}
Info & positionInfoAt (int place) const
{
Node *temp = head;
int i = 0;
while (i < place && temp != NULL)
{
temp = temp->next;
++i;
}
return temp->information;
}
void erase ()
{
removeAll ();
}
void printAll () const
{
Node *current = head;
cout << "Printing sequence!" << endl;
while (current != NULL)
{
if (current->next == NULL)
{
cout << "ID: " << current->ID;
cout << " Info: " << current->information << endl;
cout << "______END______" << endl;
}
else
{
cout << "ID: " << current->ID;
cout << " Info: " << current->information << endl;
}
current = current->next;
}
}
int size () const
{
return numberOfNode;
}
bool empty () const
{
return numberOfNode == 0;
}
};
template <typename Key, typename Info> Sequence<Key, Info>
shuffle ( const Sequence<Key, Info> & source1, int startIndex1, int length1,
const Sequence<Key, Info> & source2, int startIndex2, int length2){
//Here is where i need help
}
int main ()
{
Sequence <int, int>seq1;
Sequence <int, int>seq2;
return 0;
}
The interleaving is the easy part. Given two input sequences and an output sequence:
while ((inputSeq1 has content) or (inputSeq2 has content))
{
for (int i = 0; (inputSeq1 has content) && i < 3; i++)
{
remove item from inputSeq1
append to outputSeq
}
for (int i = 0; (inputSeq2 has content) && i < 2; i++)
{
remove item from inputSeq2
append to outputSeq
}
}
That's the basic idea. You don't say whether you should stop the interleaving if one of the lists runs out of items, so I assumed you wanted everything.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed yesterday.
Improve this question
I am trying to make a quicksort algorithm for singly-linked lists. I, however, must be somehow creating a cyclical list in the process. In the concatenate function, the while loop gets stuck printing out 2 and 22 continuously. So, I assume that I must somehow be creating a list where Node 2 points to Node 22 and vice versa. Unfortunately, I have no idea how, since I feel like I have added nullptr to the end of every list where it would matter. I have reviewed my partition function so many times I add more bugs than I fix. Is there something I am missing with how linked lists work?
I have been stuck on this for a while so any help would be greatly appreciated.
Here is my quicksort code.
// quick.cpp
#include "volsort.h"
#include <iostream>
#include <string>
using namespace std;
// Prototypes
Node *qsort(Node *head, bool numeric);
void partition(Node *head, Node *pivot, Node *&left, Node *&right, bool numeric);
Node *concatenate(Node *left, Node *right);
// Implementations
void quick_sort(List &l, bool numeric) {
l.head = qsort(l.head, numeric);
}
Node *qsort(Node *head, bool numeric) {
if (head == nullptr || head->next == nullptr) {
return head;
}
Node *l = nullptr;
Node *r = nullptr;
partition(head, head, l, r, numeric);
l = qsort(l, numeric);
r = qsort(r, numeric);
head = concatenate(l, head);
head = concatenate(head, r);
return head;
}
void partition(Node *head, Node *pivot, Node *&left, Node *&right, bool numeric) {
Node *cur = pivot->next;
bool c;
Node *tl=nullptr, *tr=nullptr;
while (cur != pivot && cur != nullptr) {
if (numeric) {
c = node_number_compare(cur, pivot);//compare numeric elements of the Nodes
}
else {
c = node_string_compare(cur, pivot);//compare string elements of the code
}
if (c) {
if (left == nullptr) {
left = cur;
cur = cur->next;
tl = left;
}
else {
tl->next = cur;
cur = cur->next;
tl = tl->next;
tl->next = nullptr;
}
}
else {
if (right == nullptr) {
right = cur;
cur = cur->next;
tr = right;
}
else {
tr->next = cur;
cur = cur->next;
tr = tr->next;
tr->next = nullptr;
}
}
}
}
Node *concatenate(Node *left, Node *right) {
if (right == nullptr && left == nullptr) {
return nullptr;
}
else if (left == nullptr) {
right->next = nullptr;
return right;
}
else if (right == nullptr) {
left->next = nullptr;
return left;
}
Node *t = left;
while (t->next != nullptr) {
cout << t->number << endl;
t = t->next;
}
t->next = right;
while (t->next != nullptr) {
cout << t->number << endl;
t = t->next;
}
t->next = nullptr;
return left;
}
Input:
45
4
9
22
2
Here's the list class functions if it helps.
#include "volsort.h"
#include <string>
#include <iostream>
List::List() {
head = NULL;
size = 0;
}
List::~List() {
if (head != NULL) { // follow the links, destroying as we go
Node *p = head;
while (p != NULL) {
Node *next = p->next; // retrieve this node's "next" before destroy it
delete p;
p = next;
}
}
}
bool node_number_compare(const Node *a, const Node *b) {
if (a->number <= b-> number) {
return true;
}
else {
return false;
}
}
bool node_string_compare(const Node *a, const Node *b) {
return a->string <= b->string;
}
void List::push_front(const std::string &s) {
Node *node = new Node();
node->next = NULL;
node->string = s;
node->number = std::stoi(s);
if (head == NULL) {
head = node;
size = 1;
}
else {
Node *p = head;
while (p->next != NULL) {p = p->next;} // go to end of list
p->next = node;
size++;
}
}
void List::dump_node(Node *n) {
while (n->next != NULL) {
std::cout << n->number << " " << n->string << std::endl;
}
}
i have 2 doubly linked list within nodes, i compare data of nodes and if data of node of second list is bigger than data of node of first list, i will chande nodes. How can i do that.
this deletes old nodes and adds that given nodes.
void DoubleLinkedList::SwitchNodesFromList(Node* changeNode, int index)
{
RemoveAt(index);
if (index < 0 || index > size)
throw "Error";
if (index == 0)
{
head = changeNode;
if (head->next != NULL)
head->next->prev = head;
}
else
{
Node* prv = findPreviousByPosition(index);
prv->next = changeNode;
if (prv->next->next != NULL)
prv->next->next->prev = prv->next;
}
}
that keeps nodes these will change
void ListController::SwitchNodes(Node* firstNodeOfList, Node* secondNodeOfList, int index)
{
Node* first = firstNodeOfList;
Node* second = secondNodeOfList;
Node* temp = first;
first->next = second->next;
first->prev = second->prev;
second->next = temp->next;
second->prev = temp->prev;
firstList->SwitchNodesFromList(second, index);
secondList->SwitchNodesFromList(first, index);
delete temp;
}
i compare item but i cant switch nodes
void ListController::CompareItemsOfNodes()
{
for (int i = 0; i < firstList->Count(); i++)
{
if (firstList->ElementAt(i) > secondList->ElementAt(i))
{
ReverseList(firstList);
}
else if (firstList->ElementAt(i) == secondList->ElementAt(i))
{
ReverseList(secondList);
}
else if (firstList->ElementAt(i) < secondList->ElementAt(i))
{
SwitchNodes(firstList->GetNode(i), secondList->GetNode(i), i);
}
}
}
I've been struggling with this last function (list_copy_front). The function is for a linked list, it is supposed to return the value of the head pointer for a new list that contains copies of the first n nodes that the source pointer points to. Also if there is less than n nodes in the source then just copy all. Currently, when I run it as is I get a nasty Segmentation Fault SIGSEGV error. The debugger says the error happens at "Node *cursor = source_ptr-> link; Any help would be greatly appreciated, thank you.
Here is some relevant info,
struct Node
{
typedef int Item;
Item data;
Node *link;
};
void list_tail_attach(Node*& head_ptr, const Node::Item& entry);
Node* list_copy_front(Node* source_ptr, size_t n);
void list_tail_attach(Node*& head_ptr, const Node::Item& entry)
{
Node *last = new Node;
last->data = entry;
last->link = NULL;
if(head_ptr == NULL)
{
head_ptr = last;
}
else
{
Node *temp = new Node;
temp = head_ptr;
while(temp->link != NULL)
{
temp = temp->link;
}
temp->link = last;
}
}
Node* list_copy_front(Node* source_ptr, size_t n)
{
Node *new_head_ptr = new Node;
Node *cursor = source_ptr->link;
size_t i = 0;
for(i = 0; i < n; i++)
{
list_tail_attach(new_head_ptr, cursor->data);
cursor = cursor->link;
}
return new_head_ptr;
}
Here's the Main test for the function
int test4()
{
Node* list = NULL; // an empty list
Node* copy = NULL;
copy = list_copy_front(list, 3);
if(copy != NULL)
{
cout << "list_copy_front function doesn't work for copying empty list\n";
return 0;
}
for(int i = 1; i <= 4; i++)
list_tail_attach(list, i);
// list contains 1, 2, 3, 4
copy = list_copy_front(list, 3);
if(list_length(copy) != 3 || copy->data != 1 || copy->link->data != 2 || copy->link->link->data != 3 )
{
cout << "list_copy_front function doesn't work\n";
return 0;
}
copy->link->data = 100;
if(list->link->data == 100)
{
cout << "list_copy_front function doesn't work.\n";
return 0;
}
list_clear(copy);
copy = list_copy_front(list, 6);
if(list_length(copy) != 4)
{
cout << "list_copy_front function doesn't work\n";
return 0;
}
cout << "list_copy_front passes the test\n";
list_clear(list);
for(int i = 1; i <= 3; i++)
list_head_insert(list, i);
// list contains 3, 2, 1
list_copy(list, copy);
if(list_length(copy) != 3 || copy->data != 3 || copy->link->data != 2 || copy->link->link->data != 1 )
{
cout << "list_copy function doesn't work\n";
return 0;
}
cout << "list_copy function passes the test\n";
return 2;
}
Edit 3
So far here's what I'm working with I appreciate the comments so far it's just not quite working out. Which is probably my fault for not explaining better.
void list_tail_attach(Node*& head_ptr, const Node::Item& entry)
{
Node *last = new Node; // Creates new Node
last->data = entry; // Points last to data
last->link = NULL;
if(last == NULL)
{
return;
}
if(head_ptr == NULL)
{
head_ptr = last;
}
else
{
Node *temp = head_ptr;
while(temp->link != NULL)
{
temp = temp->link;
}
temp->link = last;
}
}
Node* list_copy_front(Node* source_ptr, size_t n)
{
if(source_ptr == NULL)
{
return NULL;
}
Node *new_head_ptr = new Node;
Node *cursor = source_ptr;
size_t i = 0;
while(cursor!= NULL && i < n)
{
list_tail_attach(new_head_ptr, cursor->data);
cursor = cursor->link;
i++;
}
return new_head_ptr;
}
I am not allowed to change the way the function takes it's input so, that's why I left Node *last.
I left list_tail_attach(new_head_ptr, cursor->data) because without it I get an invalid conversion error. However when I run the above code I still receive an SIGSEGV error for while(temp->link != NULL) in list_tail_attach and on list_tail_attach(new_head_ptr, cursor->data); in list_copy_front.
Thank you if you are able to comment further
The first test case
Node* list = NULL; // an empty list
Node* copy = NULL;
copy = list_copy_front(list, 3);
gives Node* source_ptr == NULL and expects your function to handle it gracefully.
The function code soon tries to dereference NULL
Node *cursor = source_ptr->link;
The result is a segfault.
First is list_tail_attach, this function I assumed to be attaching an existing Node into a linked list. If the linked list is null then the Node become the head
void list_tail_attach(Node *& head_ptr, Node *& entry)
{
if (entry == NULL) {
return;
}
if (head_ptr == NULL)
{
head_ptr = entry;
}
else
{
Node *temp = head_ptr;
while (temp->link != NULL)
{
temp = temp->link;
}
temp->link = entry;
}
}
I changed the entry into a reference to a pointer to made it easier.
Ok, now move on to the list_copy_front
Node * list_copy_front(Node* source_ptr, size_t n)
{
if (source_ptr == NULL) {
return NULL;
}
Node * new_head_ptr = new Node;
Node * cursor = source_ptr;
size_t i = 0;
while(cursor != NULL && i < n){
list_tail_attach(new_head_ptr, cursor);
cursor = cursor->link;
i++;
}
return new_head_ptr;
}
You have to guard the source_ptr in case it is null.
To attach a new Node
for (int x = 0; x < 5; x++) {
Node * tmp = new Node();
tmp->data = x;
tmp->link = NULL;
list_tail_attach(list, tmp);
}
My professor helped me out with the correct solution. For anyone who views this in the future...
Node* list_copy_front(Node* source_ptr, size_t n)
{
if(source_ptr == NULL) // Takes care of NULL case
{
return NULL;
}
Node *new_head_ptr = NULL; // Creates new head and ensures NULL
Node *cursor = source_ptr; // Sets temp Node = to source
size_t i = 0; // Initializes temp variable
while(cursor!= NULL && i < n) // Loop that continues while n is bigger than i and it is not NULL
{
list_tail_attach(new_head_ptr, cursor->data);
cursor = cursor->link; // Attaches to new list
i++; // Increases count
}
return new_head_ptr;
}
The line that needed to be changed was
Node * new_head_ptr = new Node;
to
Node * new_head_ptr = NULL;
When I run valgrind, I get one error at method insert for operator new;
I know this probably means that I have to delete node n how I tried so many things to try to delete it but it just gives me even more errors. Please hel.
class key_value_sequences {
public:
struct node{
int key;
vector<int> values;
node* next;
node* prev;
};
key_value_sequences() {
}
~key_value_sequences() {
}
key_value_sequences(const key_value_sequences& A) {
n = A.n;
head = A.head;
tail = A.tail;
v = A.v;
}
key_value_sequences& operator=(const key_value_sequences& A) {
if (this == &A) return *this;
n = A.n;
head = A.head;
tail = A.tail;
v = A.v;
return *this;
}
// YOU SHOULD USE C++ CONTAINERS TO AVOID RAW POINTERS
// IF YOU DECIDE TO USE POINTERS, MAKE SURE THAT YOU MANAGE MEMORY PROPERLY
// IMPLEMENT ME: SHOULD RETURN SIZE OF A SEQUENCE FOR GIVEN KEY
// IF NO SEQUENCE EXISTS FOR A GIVEN KEY RETURN -1
int size(int key) const {
if (find(v.begin(), v.end(), key)!=v.end()) {
node* temp = head;
while(temp != NULL) {
if (temp->key == key) {
return temp->values.size();
}
else temp = temp->next;
}
}
else return -1;
}
// IMPLEMENT ME: SHOULD RETURN POINTER TO A SEQUENCE FOR GIVEN KEY
// IF NO SEQUENCE EXISTS FOR A GIVEN KEY RETURN nullptr
const int* data(int key) const {
if (find(v.begin(), v.end(), key)!=v.end()) {
node* temp = head;
while(temp != NULL) {
if (temp->key == key) {
return temp->values.data();
}
else temp = temp->next;
}
}
else return nullptr;
}
// IMPLEMENT ME: INSERT VALUE INTO A SEQUENCE IDENTIFIED BY GIVEN KEY
void insert(int key, int value) {
if(v.size() == 0) { //empty list
v.push_back(key);
n = new node;
n->prev = NULL;
n->key = key;
n->values.push_back(value);
head = n;
tail = n;
}
else if((find(v.begin(), v.end(), key)!=v.end())) { //if key exists already
node* temp = head;
while(temp != NULL) {
if (temp->key == key) {
temp->values.push_back(value);
break;
}
else temp = temp->next;
}
}
else { //if theres no existing key
v.push_back(key);
n = new node;
n->key = key;
n->values.push_back(value);
n->prev = tail;
tail->next = n;
tail = n;
tail->next = NULL;
}
}
private:
vector<int> v;
node* n;
node* head;
node* tail;
}; // class key_value_sequences
#endif // A3_HPP
In insert method:
if(v.size() == 0) { //empty list
v.push_back(key);
n = new node;
n->prev = NULL;
n->key = key;
n->values.push_back(value);
head = n;
tail = n;
}
You are not setting the head->next to NULL. I suspect that could be the problem while inserting second value.
while(temp != NULL) { // <<<<< Is temp uninitialized?
if (temp->key == key) {
temp->values.push_back(value);
break;
}
else temp = temp->next;
Its pretty dangerous to not initialize the pointer to NULL
so, I am really new to programming, and I am taking a c++ class right now, in which I need to write and implement and AVL Tree, using a Doubly Linked lists to print off the contents of my tree, level by level. The teacher is really picky, so we can't use any containers from the standard libraries. My Doubly Linked list should be working fine, because I used it on a previous project, but I am getting an error when trying to combine it with the AVL Tree. I know my code probably has A LOT of things that need to be modified, but one step at a time. I am getting the following error, so I was wondering if you guys could help me figure out how to fix it. Also, if you have any suggestions on how to better my code, I would appreciate it.
In instantiation of ‘void AVLTreeSet::print(std::ofstream&) [with ItemType = std::basic_string; std::ofstream = std::basic_ofstream]’:
Lab6/main.cpp:80:20: required from here
Lab6/AVLTreeSet.h:152:49: error: cannot convert ‘LinkedList >::AVLNode*>::Node*’ to ‘AVLTreeSet >::AVLNode*’ in initialization
AVLNode* n = MyList.remove(i);
This is my AVLTree.h:
#pragma once
#include <fstream>
#include "LinkedList.h"
using namespace std;
template <typename ItemType>
class AVLTreeSet {
struct AVLNode {
ItemType item;
int height;
AVLNode* left;
AVLNode* right;
AVLNode(const ItemType& _item, AVLNode* _left = NULL, AVLNode* _right = NULL, int _height = 0) :
item(_item), left(_left), right(_right), height(_height) {}
};
AVLNode* root;
int size = 0;
public:
void RemoveBelowRoot(AVLNode *& n, const ItemType& item)
{
if (n == NULL)
{
return;
}
else if(item < n->item)
{
RemoveBelowRoot(n->left, item);
}
else if(item > n->item)
{
RemoveBelowRoot(n->right, item);
}
else if(n->left == NULL)
{
n = n->right;
}
else if (n->right == NULL)
{
n = n->left;
}
else
{
n = findMin(n->right);
RemoveBelowRoot(n->right, n->item);
}
balance(n);
size--;
// update height of nodes on this path
}
AVLNode * findMin(AVLNode* n)
{
if (n == NULL)
{
return n;
}
else if (n->left->item < n->item)
{
findMin(n->left);
}
else if(n->left->item > n->item)
{
findMin(n->right);
}
return n;
}
void remove(const ItemType& item) {
RemoveBelowRoot(root, item);
}
bool find(const ItemType& item) {
if (findBelowRoot(root, item))
{
return true;
}
return false;
}
bool findBelowRoot(AVLNode * n, const ItemType& data)
{
if (n->item == data)
{
return true;
}
else if (data > n->item)
{
findBelowRoot(n->right, data);
}
else if (data < n->item)
{
findBelowRoot(n->left, data);
}
}
void clear()
{
while (getHeight(root) != 0)
{
// remove
}
}
void addBelowRoot(AVLNode *& n, const ItemType& item)
{
if (n == NULL)
{
n = new AVLNode(item);
size++;
}
else if (item < n->item)
{
addBelowRoot(n->left, item);
}
else if(item > n->item)
{
addBelowRoot(n->right, item);
}
}
void add(const ItemType& item) {
addBelowRoot(root, item);
}
void print (ofstream& out)
{
if (root == NULL)
{
return;
}
else {
LinkedList<AVLNode *> MyList;
MyList.insert(0, root); // add root to Q
while (MyList.getSize() != 0) // While Q is not empty
//(figure out how many items are in that level)(levelsize = Q.size();)
{
for (auto i = 0; i < MyList.getSize(); i++) // for (int 1 = 0; i < LEVELSIZE; i++)
{
AVLNode* n = MyList.remove(i);
out << "level " << i << " " << n->item << "(" << n->height << ") ";
if (n->left != NULL) {
MyList.insert(MyList.getSize(), n->left);
}
if (n->right != NULL) {
MyList.insert(MyList.getSize(), n->right);
}
}
}
out << "\n ";
}
}
void balance (AVLNode *n)
{
if (getHeight(n->left) - getHeight(n->right))
{
balanceToRight(n);
}
if (getHeight(n->right) - getHeight(n->left))
{
balanceToLeft(n);
}
}
int getHeight(AVLNode *& n)
{
if (n == NULL)
{
return 0;
}
else
{
return n->height;
}
}
void balanceToRight(AVLNode * n)
{
if (getHeight(n->left->right) > getHeight(n->left->left))
{
rotateLeft(n->left);
}
rotateRight(n);
}
void rotateRight(AVLNode *&n)
{
AVLNode * k = n->left;
n->left = k->right;
k->right = n;
n = k;
// update heights of k and n
}
void rotateLeft(AVLNode *& n)
{
AVLNode * k = n->right;
n->right = k->left;
k->left = n;
n = k;
// update heights of k and n
}
void balanceToLeft(AVLNode * n)
{
if (getHeight(n->right->left) > getHeight(n->right->right)) // check with TAs if this is right
{
rotateRight(n);
}
rotateLeft(n);
}
/*void updateHeight(AVLNode *& n)
{
}*/
};
Now this is my LinkedList.h
#pragma once
#include <iostream>
#include <cstddef>
#include <fstream>
using namespace std;
template <typename ItemType>
class LinkedList {
struct Node {
ItemType item;
Node *next;
Node *prev;
Node(const ItemType &_item, Node *_next = NULL, Node *_prev = NULL) :
item(_item), next(_next), prev(_prev) { }
};
Node *head;
Node *tail;
int size = 0;
public:
~LinkedList()
{
clear();
}
void insert(int index, ItemType& item) {
if (index > size || size < 0)
{
return;
}
Node * newNode = new Node(item);
if (size == 0)
{
head = newNode;
tail = newNode;
newNode->next = NULL;
newNode->prev = NULL;
size++;
}
else if (index == 0)
{
head->prev = newNode;
newNode->next = head;
head = newNode;
size++;
}
else if (index == size) //INSERTING AT THE END
{
newNode->prev = tail;
newNode->next = NULL;
tail->next = newNode;
tail = newNode;
size++;
}
else {
Node* n = find_node(index);
newNode->next = n;
newNode->prev = n->prev;
n->prev->next = newNode;
n->prev = newNode;
size++;
}
}
Node * remove(int index) {
if (head == NULL || index >= size || index < 0)
{
return NULL;
}
else {
Node* name = find_node(index);
Node * n;
if (size == 1) // REMOVE THE ONLY NODE
{
n = head;
head = NULL;
tail = NULL;
size--;
}
else if (index == 0) //REMOVE THE FIRST NODE WHEN THERE'S MORE THAN ONE IN THE LIST
{
n = head;
head = head->next;
head->prev = NULL;
size--;
}
else if (index == size-1) //REMOVE THE LAST WHEN THERE'S MORE THAN ONE NODE IN THE LIST
{
n = tail;
tail = n->prev;
tail->next = NULL;
size--;
}
else
{
n = find_node(index);
n->prev->next = n->next;
n->next->prev = n->prev;
size--;
}
delete n;
return name;
}
}
Node * find_node(int index)
{
Node * n = NULL;
if (0 <= index && index <= size/2)
{
n = head;
for (int i = 0; i < index; i++)
{
n = n->next;
}
}
else if (size/2 < index && index <= size-1)
{
n = tail;
for (unsigned i = size-1; i > index; i--)
{
n = n->prev;
}
}
return n;
}
int getSize()
{
return size;
}
/* void print(LinkedList <string>& list, ofstream& out, int i)
{
if(head == NULL)
{
return;
}
out << "node " << i << ": " << getItem(i) << "\n";
}
Node* getItem(const int index)
{
if (index > size)
{
return NULL;
}
Node* temp = head;
for (unsigned i = 0; i < size; i++)
{
if (i == index)
{
return temp;
}
temp = temp-> next;
}
return NULL;
}*/
/* int find(const ItemType& item) {
Node * NodeP = head;
for (unsigned i = 0; i < size; i++)
{
if (NodeP->item == item)
{
return i;
}
NodeP = NodeP->next;
}
return -1;
}*/
void clear()
{
while (size != 0){
remove(0);
}
}
};
Thanks so much!
LinkedList::remove returns a LinkedList::Node pointer. You are trying to assign that into an AVLTreeSet::AVLNode pointer.
The AVLTreeSet::AVLNode * you are looking for is in the item member of the returned Node pointer.
You could do something like:
LinkedList<AVLNode *>::Node* n = MyList.remove(i);
AVLNode *treeNode = n->item;
Notes
You should be checking for NULL as the return value for remove, if it doesn't find anything.
remove actually deletes the node then returns it. You are then accessing something that has been deleted, which is Undefined Behavior. You really need to fix this before you go much further.
your for loop will only remove about half of the objects, as your are removing items from the list while still iterating further along the list using i.