I have just start C++ and learned about pointers and I need some hints.
The code is about splitting a forward list into two (*this and *other). I think I have gotten the finding mid point right but I am really confuse about the pointers at the end (causing errors). I think I might have pointed ptr to lists but I am not sure. Can someone please giving me some ideas.
template <typename T>
class Forward_list
{
public:
class Node
{
public:
// A node will hold data of type T
T data{};
// next will point to the next node in the list
// we initialise next to nullptr
Node* next = nullptr;
Node(){}
Node(T input_data, Node* next_node= nullptr)
{
data = input_data;
next = next_node;
}
// Destructor
~Node(){}
};
private:
// private member variables for Forward_list
unsigned size_ = 0;
Node* head_ = nullptr;
template <typename T>
Forward_list<T> Forward_list<T>::split() {
Node* other = nullptr;
Node* tmp = this->head_;
struct Node* current = this->head_;
int length = this->size();
int mid = (length-1) / 2;
for(int i = 0; i < mid; i++) {
tmp = tmp->next;
}
*other = current->next;
current->next = nullptr;
return *this;
}
Not sure if this is enough to be understood. Thanks for the help.
Related
i am trying to build a split function for a linkedlist, so i need to split my linkedlist into a half and i need to update the size of linkedlist as well, when i execute my code it returned with segmentation fault i am not sure what is wrong with my code can you help me thank you :), i am sorry for bad code
LinkedList<T> LinkedList<T>::split() {
Node* head_ptr = this -> head_;
LinkedList<int>* other = new LinkedList<int>();
if(this -> size_ % 2 != 0){
this -> size_ += 1;
}
int a = this -> size_ / 2;
int i = 1;
while(i < a){
head_ptr = head_ptr -> next;
}
other -> head_ = head_ptr -> next;
head_ptr -> next = nullptr;
Node * new_other = other -> head_;
while(new_other != nullptr){
other -> size_++;
new_other = new_other -> next;
}
this -> size_ = this -> size_ / 2;
return *other;
}
For my node structure:
class Node
{
public:
T data{};
Node* next = nullptr;
};
For my LinkedList class:
template <typename T>
class LinkedList
{
private Node* head_ = nullptr;
private int size_ = 0;
LinkedList(const LinkedList<T>& other);
LinkedList(std::initializer_list<T> input);
void push(const T& data);
void pop();
LinkedList<T> LinkedList<t>::split();
Splitting a linked list given only the head pointer involves walking the list with a slow and fast pointer, and it seems somewhat evident you already know this. The difficult part is knowing where to terminate and how to then handle the two resulting lists.
First, make a private ctor that only you will be calling (from something like your split()). The purpose of this is to feed a new LinkedList instance a predetermined list head and size. It will come in handy later. It may look like this (assuming it is in your class-def, otherwise adjust accordingly):
// purposely private
LinkedList(Node *head, size_t siz)
: head_(head)
, size_(siz)
{
}
Armed with that, you can make a trivial splitter by using a slow-pointer that happens to also be a pointer-to-pointer (which will become very handy for setting the left-side list terminator), and a fast pointer to double-hop the list as long as possible.
LinkedList split()
{
size_t lsize = 0;
Node **pp = &head_;
Node *fast = head_;
while (fast && fast->next)
{
++lsize;
pp = &(*pp)->next;
fast = fast->next->next;
}
Node *p = *pp; // remember head of right list
*pp = nullptr; // terminate left list
// adjust sizes
size_t rsize = size_ - lsize;
size_ = lsize;
return LinkedList(p, rsize); // remember that funky ctor??
}
That's all there is to it. Note that due to the even/odd possible node count, this will always bias the right side getting the extra node if there is one. If the count is even this will split the list perfectly, retaining the left side in the current list and returning the right side as the result value. Also note that if you invoke this with a single-node list the current list will be emptied and the return result will harbor that single node.
I had a bit of trouble understanding how you wanted to handle the split but could you try something like this?
LinkedList<T> LinkedList<T>::split() {
LinkedList<T> second_list;
Node* current = head_;
Node* second_current = second_list.head_;
while (current->next != nullptr) {
if (current->next->next != nullptr) {
current = current->next->next;
second_current = second_current->next;
}
else {
current = current->next;
second_current = second_current->next;
}
}
current->next = nullptr;
second_current->next = nullptr;
return second_list;
}
template<typename T>
LinkedStack<T>::LinkedStack(const LinkedStack<T> &other) {
Node<T> *temp = other.stktop;
if (other.stktop != nullptr) {
Node<T> *newnode = new Node<T>;
newnode = temp;
while (temp->next != nullptr) {
temp = temp->next;
newnode->next = temp;
}
}
}
This is my copy constructor.
template <typename U>
struct Node {
U data;
Node<U> *next;
};
Node<T> *stktop;
and this is my struct node located in private section of my LinkedStack Class.
I tried following the logic for writing the copy constructors and I came up with this code.However it doesn't work.Any idea what is wrong?
Something like that:
template<typename T>
LinkedStack<T>::LinkedStack(const LinkedStack<T> &other)
{
// Create first node
if (!other.stktop) // Use pointer to bool cast
{
stktop = new Node<T>;
// Copy data. This is the simplest copy if U support it.
stktop->data = other.stktop->data;
}
else
{
stktop = nullptr; // Very important otherwise its value is undefined
return;
}
auto pothernode = other.stktop;
auto pthisnode = stktop;
// Iterate overall the elements
while (pothernode->next)
{
pthisnode->next = new Node<T>;
pthisnode->next->data = pothernode->next->data;
pothernode = pothernode->next;
pthisnode = pthisnode->next;
}
}
Note that all the nodes are allocated on the heap so do not forget to delete them. I suggest to use std::unique_ptr or std::shared_ptr instead of pure pointer.
Some possible optimization:
template<typename T>
LinkedStack<T>::LinkedStack(const LinkedStack<T> &other)
{
const auto& pothernode = other.stktop;
auto& pthisnode = stktop;
pthisnode = nullptr;
// Iterate overall the elements
while (pothernode)
{
pthisnode = new Node<T>;
pthisnode->data = pothernode->data;
pothernode = pothernode->next;
pthisnode = pthisnode->next;
}
}
I was trying to create a linked list using a for loop but the 'new' in the for loop in the create() method didn't quite allocate a new slot to store new data. As a result, when I tried to print the list, I got an infinite loop. Can somebody tell me what's wrong here?
struct node
{
double value;
node * next_ptr;
node(){}
node(double val, node * p): value(val), next_ptr(p) {}
~node(){}
};
node * create()
{
using namespace std;
node temp = {0, nullptr};
node * result;
for(int i=1; i<5; ++i)
{
result = new node;
result->value = i;
result->next_ptr = &temp;
temp = *result;
}
return result;
};
The reason you are probably getting an infinite loop is because in:
temp = *result;
you are copying the value of *result into a new object of type node, which is unrelated to the one you created.
What you want to do is store a pointer instead:
node* temp = nullptr;
node* result;
for(int i=0; i<5; ++i)
{
result = new node;
result->value = i;
result->next_ptr = temp;
temp = result;
}
return result;
Live demo
A part from the learning value, just stick to std::forward_list or std::list, for lists, instead. Or even better just use std::vector or other containers (depending on the use that you make of the container).
a simple one to create linked in for loop
#include <iostream>
class LinkedList {
public:
int value;
LinkedList * next;
};
int main()
{
LinkedList *List = nullptr;
LinkedList *head = List;
LinkedList *prev;
for (int i=0; i< 3;i++)
{
LinkedList *temp = new(LinkedList);
temp->value = i;
temp->next = nullptr;
if (head == nullptr)
{
head = temp;
prev = head;
}
else
{
prev->next = temp;
prev = temp;
}
}
}
I have problem with my assignment operator in my double directed circular list.
when I have a list with content and assign another list with content to it the numbers are jumbled up. The input I use is 5 20 10 but when I print my list the output is 5 10 20. My code looks like this:
#ifndef CDDLIST_H
#define CDDLIST_H
template <typename T>
class CircularDoubleDirectedList<T>{
public:
static enum direction{ FORWARD, BACKWARD };
CircularDoubleDirectedList<T>& operator= (const CircularDoubleDirectedList<T>& obj);
void addAtCurrent(const T& data);
private:
class Node{
public:
T data;
Node *next;
Node *previous;
Node(const T& data){
this->data = data;
this->next = nullptr;
this->previous = nullptr;
};
Node(){
this->data = NULL;
this->next = nullptr;
this->previous = nullptr;
};
~Node(){};
};
Node *current;
direction currentDirection;
int numberOfElements;
};
template <typename T>
CircularDoubleDirectedList<T>& CircularDoubleDirectedList<T>::operator= (const CircularDoubleDirectedList<T>& obj){
if (this !=&obj){
this->currentDirection = obj.currentDirection;
this->current = nullptr;
this->numberOfElements = 0;
Node* walker = obj.current;
for (int i = 0; i < obj.numberOfElements; i++){
walker = walker->previous;
addAtCurrent(walker->data);
}
}
return *this;
}
template <typename T>
void CircularDoubleDirectedList<T>::addAtCurrent(const T& data){
if (this->numberOfElements == 0){
Node *node = new Node(data);
this->current = node;
node->next = node;
node->previous = node;
this->numberOfElements++;
}
else{
Node *node = new Node(data);
node->previous = this->current;
node->next = this->current->next;
this->current->next = node;
this->current = node;
this->current->next->previous=this->current;
this->numberOfElements++;
}
}
#endif
I have tried to use two walkers, changed direction of the walker(s), moved the walker(s) first and added data second, moved one walker backwards and the other forwards, etc.
Your assignment code is adding the elements of obj to this in reverse order, because it's stepping through the previous pointers instead of next. Change
walker = walker->previous;
to
walker = walker->next;
I'm trying to write an insert function for string values for a circular doubly linked list. I saw that creating a dummy node is beneficial in doing this so I can eliminate special cases like when the list is empty. The problem is I'm not finding alot of good information on dummy head nodes. I understand their purpose, but I don't understand how I create/implement it.
appreciate all the code examples guys, tried to figure it out on my own getting a little stuck though if someone can look at it.
#include <iostream>
#include <string>
using namespace std;
typedef string ListItemType;
struct node {
node * next;
node * prev;
ListItemType value;
};
node * head;
node * dummyHead = new node;
void insert(const ListItemType input, node * & within);
void main(){
insert("bob",dummyHead);
}
void insert( const ListItemType input, node * &ListHead){
node *newPtr = new node;
node *curr;
newPtr->value = input;
curr = ListHead->next; //point to first node;
while (curr != ListHead && input < curr->value){
curr = curr->next;
}
//insert the new node pointed to by the newPTr before
// the node pointed to by curr
newPtr->next = curr;
newPtr->prev = curr->prev;
curr->prev = newPtr;
newPtr->prev->next = newPtr;
}
For a circular doubly linked list, you can setup 1 sentinel node where both "next" and "prev" points to itself when list is empty. When list is not empty, sentinel->next points to first element and sentinel->prev points to last element. With this knowledge, your insert and remove function would look something like this.
This is very basic and your LinkedList and Node class maybe implemented differently. That is OK. The main thing is the insert() and remove() function implementation that shows how sentinel node(s) removes the need for checking for NULL values.
Hope this helps.
class DoublyLinkedList
{
Node *sentinel;
int size = 0;
public DoublyLinkedList() {
sentinel = new Node(null);
}
// Insert to the end of the list
public void insert(Node *node) {
// being the last node, point next to sentinel
node->next = sentinel;
// previous would be whatever sentinel->prev is pointing previously
node->prev = sentinel->prev;
// setup previous node->next to point to newly inserted node
node->prev->next = node;
// sentinel previous points to new current last node
sentinel->prev = node;
size++;
}
public Node* remove(int index) {
if(index<0 || index>=size) throw new NoSuchElementException();
Node *retval = sentinel->next;
while(index!=0) {
retval=retval->next;
index--;
}
retval->prev->next = retval->next;
retval->next->prev = retval->prev;
size--;
return retval;
}
}
class Node
{
friend class DoublyLinkedList;
string *value;
Node *next;
Node *prev;
public Node(string *value) {
this->value = value;
next = this;
prev = this;
}
public string* value() { return value; }
}
Why are you trying to use dummy node?
I hope you can handle it without a dummy node.
Eg:
void AddNode(Node node)
{
if(ptrHead == NULL)
{
ptrHead = node;
}else
{
Node* itr = ptrHead;
for(int i=1; i<listSize; i++)
{
itr = itr->next;
}
itr->next = node;
}
listSize++;
}
The above one is an example to handle the linked list without dummy node.
For a circular double linked list without a dummy node, the first node previous pointer points to the last node, and the last node next pointer points to the first node. The list itself has a head pointer to first node and optionally a tail pointer to last node and/or a count.
With a dummy node, the first node previous pointer points to the dummy node and the last node next pointer points to the dummy node. The dummy nodes pointers can point to the dummy node itself or be null.
The HP / Microsoft STL list function uses a dummy node as a list head node with the next pointer used as a head pointer to the first real node, and the previous pointer used as a tail pointer to the last real node.
#include <iostream>
#include <string>
using namespace std;
typedef string ElementType;
struct Node
{
Node(){}
Node(ElementType element, Node* prev = NULL, Node* next = NULL):element(element){}
ElementType element;
Node* prev;
Node* next;
};
class LinkList
{
public:
LinkList()
{
head = tail = dummyHead = new Node("Dummy Head", NULL, NULL);
dummyHead->next = dummyHead;
dummyHead->prev = dummyHead;
numberOfElement = 0;
}
void insert(ElementType element)
{
Node* temp = new Node(element, NULL, NULL);
if (0 == numberOfElement)
{
head = tail = temp;
head->prev = dummyHead;
dummyHead->next = head;
tail->next = dummyHead;
dummyHead->prev = tail;
}
else
{
tail->next = temp;
temp->prev = dummyHead->next;
temp->next = dummyHead;
dummyHead->next = temp;
tail = temp;
}
numberOfElement += 1;
}
int length() const { return numberOfElement; }
bool empty() const { return head == dummyHead; }
friend ostream& operator<< (ostream& out, const LinkList& List);
private:
Node* head;
Node* tail;
Node* dummyHead;
int numberOfElement;
};
ostream& operator<< (ostream& out, const LinkList& List)
{
Node* current = List.head;
while (current != List.dummyHead)
{
out<<current->element<<" ";
current = current->next;
}
out<<endl;
return out;
}
int main()
{
string arr[] = {"one", "two", "three", "four", "five"};
LinkList list;
int len = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < len; ++i)
{
list.insert(arr[i]);
}
cout<<list<<endl;
}
I think this code can help you. When you want to implement some data structure, you must have a clear blueprint about it.
Do the following inside the constructor
ptrHead = new Node();
listSize = 1;
if you have tail also,
ptrHead->next = ptrTail;
The above code will create dummy node.
Make sure you implementation should not affected by this dummy node.
eg:
int getSize()
{
return listSize-1;
}