I'm currently implementing a linked list (in my time off!) and am finding that I have functions with structures like this:
void traverseList(node *head){
if(head != 0){
while(head->next !=0){
cout << head->data << endl;
head = head->next;
}
//one extra for the node at the end
cout << head->data << endl;
}
}
I was wondering in anyone knew of a way to eliminate the 'one extra' calls?
Your function can be greatly simplified to:
void traverseList(node *head)
{
for(node * iterator = head; iterator; iterator = iterator->next)
{
cout << iterator->data << endl;
}
}
Change this:
if(iterator != 0){
while(iterator->next !=0){
cout << iterator->data << endl;
iterator = iterator->next;
}
//one extra for the node at the end
cout << iterator->data << endl;
}
to this:
while(iterator != 0) {
cout << iterator->data << endl;
iterator = iterator->next;
}
Related
I am trying to make a mask delivery, ordering service code.
The function order will add a new order to order list.
The function output will output the list from newest to oldest order.
The function deliver removes the oldest order.
The following is the code:
#include <iostream>
#include <string>
using namespace std;
struct Mask {
string type;
string customer;
Mask *next;
};
void order(Mask *&head, string type, string customer){
cout << "Ordering " << type << " for " << customer << endl;
Mask *oldHead = head;
head = new Mask;
head->type = type;
head->customer = customer;
head->next = oldHead;
}
void output(Mask *head){
cout << "Outputting order list " << endl;
for (Mask *p = head; p != NULL; p = p->next)
cout << " " << p->type << " for " << p->customer << endl;
}
void deliver(Mask *&head){
if (head->next == NULL){
cout << "Delivering " << head->type;
cout << " for " << head->customer << endl;
delete head;
}
else
deliver(head->next);
}
int main()
{
Mask *head = NULL;
order(head, "3M-N95", "Alice");
order(head, "OxyAir", "Burce");
order(head, "3M-N95", "Cindy");
output(head);
deliver(head);
output(head);
}
Everything runs smoothly, but it says segmentation error(core dumped) at the end. I tried adding this:
if (head->next->next == NULL){
deliver(head->next);
head->next == NULL;
}
But the problem still exists. Any help is appreciated.
I changed deliver to this:
void deliver(Mask *&head){
if (head->next->next == NULL){
cout << "Delivering " << head->next->type;
cout << " for " << head->next->customer << endl;
head->next = head->next->next;
delete head->next;
}
else
deliver(head->next);
}
Apparently, just setting the pointer to NULL does not fix the problem, so I just updated it so that the second last pointer pointed directly to the end.
in "deliver" you force the function to meet the condition if(head->next == NULL)
and then trying to reach head->next->next which is like trying to say null->next (resulting with segmentation fault).
I would recommend traversing to the last "Mask" object with a while loop instead of using all those "if" statements which lead to the same result, or at least change the second if to else if in order to avoid meeting this "if" again.
Given the name of a node, this function should search the linked list; if its found inside, then return a pointer that points to that node, otherwise return null. Note: I am certain I have written this function successfully.
// getNode
Node *LinkedList::getNode(string name)
{
Node *temp = head;
while (temp != NULL)
{
if (temp->name.compare(name) == 0)
return temp;
temp = temp->next;
}
return NULL;
}
Given a node, this function prints: teamName(winScore-loseScore) on screen. Examples: UCLA(25-13) or Texas A&M(31-25). Note: I am sure I have written this function successfully.
// printNode
void LinkedList::printNode(Node *node)
{
if (node == NULL)
return;
else {
cout << node->name << "(" << node->winScore;
cout << "-" << node->loseScore << ")";
}
}
Given a team name, this function is supposed to print all the nodes in its adjacency list one-by-one in the following format (NOTE: the following is just one example!) This is where I think I am wrong.
Missouri University beat: New Mexico(52-23), Salisbury (48-31), Virginia (34-9)
void LinkedList::printList(string name)
{
if (head == NULL)
cout << "\n Empty list" << endl;
else {
Node *temp = head;
while (temp != NULL)
{
cout << temp->name << " beat: " << temp->name << endl; // Is this right?
temp = temp->next;
}
}
}
I'm guessing that this is close to what you want:
void LinkedList::printList(string name)
{
// find the node for the name you supply
// (or else I don't understand why 'name' is supplied to this function)
Node *temp = getNode(name);
if (temp) { // node with name found
if (temp->next) { // there's at least one adjacent node
cout << temp->name << " beat: ";
while ((temp = temp->next) != nullptr) {
printNode(temp);
if (temp->next) cout << ", ";
};
cout << "\n";
} else { // no adjacent nodes
cout << temp->name << " did not beat anyone\n";
}
}
}
below is my current in-progress code converting a singly linked to a doubly linked list. I haven't touched the delete function yet. I've gotten insert in empty list, end of list, and beginning of list apparently working.
However nodes inserting in the middle seemingly fail to create a link to the previous node. My debugging lines I inserted seem to show both the n->next and n-> prev with the correct memory address, but when I go to reverseprint, any nodes inserted in the middle are missed and the links are gone. Where am I going wrong in regards to this?
Code below:
#include <iostream>
#include <string>
using namespace std;
// define a node for storage and linking
class node {
public:
string name;
node *next;
node *prev;
};
class linkedList {
public:
linkedList() :top(NULL) {}
bool empty() { return top == NULL; }
node *getTop() { return top; }
node *getEnd() { return end; }
void setTop(node *n) { top = n; }
void setEnd(node *p) { end = p; }
void add(string);
int menu();
void remove(string);
~linkedList();
void reversePrint();
friend ostream& operator << (ostream&, const linkedList&); // default output is in-order print.
private:
node *top;
node *end;
};
void main() {
linkedList l;
cout << l.empty() << endl;
int option = 0;
string s;
bool go = true;
while (go) {
option = l.menu();
switch (option) {
case 1: cout << "enter a name: "; cin >> s; l.add(s); break;
case 2: cout << "enter name to be deleted: "; cin >> s; l.remove(s); break;
case 3: cout << l; break;
//case 4: cout << "can not be done with a singly linked list" << endl;
case 4: l.reversePrint(); break;
case 5: cout << "exiting" << endl; go = false; break;
}
}
system("pause");
}
void linkedList::remove(string s) {
bool found = false;
node *curr = getTop(), *prev = NULL;
while (curr != NULL) {
// match found, delete
if (curr->name == s) {
found = true;
// found at top
if (prev == NULL) {
node *temp = getTop();
setTop(curr->next);
delete(temp);
// found in list - not top
}
else {
prev->next = curr->next;
delete(curr);
}
}
// not found, advance pointers
if (!found) {
prev = curr;
curr = curr->next;
}
// found, exit loop
else curr = NULL;
}
if (found)cout << "Deleted " << s << endl;
else cout << s << " Not Found " << endl;
}
void linkedList::add(string s) {
node *n = new node();
n->name = s;
n->next = NULL;
n->prev = NULL;
// take care of empty list case
if (empty()) {
top = n;
end = n;
// take care of node belongs at beginning case
}
else if (getTop()->name > s) {
n->next = getTop();
n->prev = NULL;
setTop(n);
node *temp;
temp = n->next;
temp->prev = n;
// take care of inorder and end insert
}
else {
// insert in order case
node *curr = getTop(), *prev = curr;
while (curr != NULL) {
if (curr->name > s)break;
prev = curr;
curr = curr->next;
}
if (curr != NULL) { // search found insert point
n->next = curr;
cout << n->name << " " << n << " prev " << prev << " " << prev->name << endl;
n->prev = prev;
prev->next = n;
cout << "n->prev is: " << n->prev << " " << n->prev->name << endl;
cout << "n->next is: " << n->next << " " << n->next->name << endl;
}
// take care of end of list insertion
else if (curr == NULL) {// search did not find insert point
prev->next = n;
n->prev = prev;
cout << "n->prev is: " << n->prev << " " << n->prev->name << endl;
setEnd(n);
}
}
}
ostream& operator << (ostream& os, const linkedList& ll) {
//linkedList x = ll; // put this in and the code blows up - why?
node *n = ll.top;
if (n == NULL)cout << "List is empty." << endl;
else
while (n != NULL) {
os << n->name << endl;
os << n << endl;
if (n->next != NULL) {
os << "next is " << n->next << endl;
}
n = n->next;
}
return os;
}
void linkedList::reversePrint() {
node *n = end;
if (n == NULL)cout << "List is empty." << endl;
else
while (n != NULL) {
//cout << n->name << endl;
cout << "memory address of " << n->name << " is " << n << endl;
if (n->prev != NULL) {
cout << "prev is " << n->prev << endl;
}
n = n->prev;
}
return;
}
// return memory to heap
linkedList::~linkedList() {
cout << "~linkedList called." << endl;
node *curr = getTop(), *del;
while (curr != NULL) {
del = curr;
curr = curr->next;
delete(del);
}
}
int linkedList::menu() {
int choice = 0;
while (choice < 1 || choice > 5) {
cout << "\nEnter your choice" << endl;
cout << " 1. Add a name." << endl;
cout << " 2. Delete a name." << endl;
cout << " 3. Show list." << endl;
cout << " 4. Show reverse list. " << endl;
cout << " 5. EXIT " << endl;
cin >> choice;
}
return choice;
}
You are not setting the prev of the current in insertion into middle, just do:
n->next = curr;
curr->prev = n; // <-- this
This is what I have so far, but it's not working. Basically skips to else if(cnode == preposition).
void LinkedList::Delete(Node *PrePosition) {
Node *cnode = head;
Node *pnode = NULL;
while (cnode != NULL) {
if (cnode->value != NULL) {
if (pnode == NULL) {
// if there is not previous node
head = cnode->next;
}
else if (cnode == PrePosition) {
// if there is previous node
cout << endl << "Deleting: " << cnode << endl;
pnode->next = cnode->next;
}
}
else {
// don't delete
pnode = cnode;
}
cnode = cnode->next;
}
}
1: Take the pointer from the previous node and point it to the next one after the one you want to delete
2: Delete the pointer from the previous node to the current node
3: Delete the pointer from the next node to the current node (if it is a doubly-linked list)
Three cases of delete in a singly linked-list:
delete the first node
void delete_first()
{
node *temp=new node;
temp=head;
head=head->next;
delete temp;
}
delete the last node
void delete_last()
{
node *current = new node;
node *previous = new node;
current=head;
while(current->next != NULL)
{
previous = current;
current = current->next;
}
tail = previous; // if you have a Node* tail member in your LinkedList
previous->next = NULL;
delete current;
}
delete at a particular position (your case)
void LinkedList::delete_position(int pos)
{
node *current=new node;
node *previous=new node;
current=head;
for(int i=1; i < pos; i++) //or i = 0; i < pos-1
{
previous=current;
current=current->next;
}
previous->next=current->next;
delete current;
}
^^ from codementor ^^
However if your function signature intends delete_node(Node* nodeToDelete) [PrePosition is not a good name in this case] and you want delete the node passed to the function without knowing its position in the list we can modify delete_position() like so:
void LinkedList::delete_node(Node* nodeToDelete)
{
node *current= head;
node *previous= nullptr;
if (head == nodeToDelete){
head = nodeToDelete->next;
delete nodeToDelete;
return
}//else
while(current != nodeToDelete)
{
previous = current;
current = current->next
}
previous->next = current->next;
delete nodeToDelete;
}
Also in your original code, if it's skipping the line you mentioned, pnode is always null when cnode has a non-null value in it.
Here are the full code
class SportShoe {
private:
struct nodeSport {
int ShoeID;
char BrandShoe[SIZE];
char TypeShoe[SIZE];
char ColourShoe[SIZE];
int SizeShoe;
float PriceShoe;
nodeSport *last;
};
nodeSport *first = NULL;
public:
int MenuSportShoe();
void AddSportShoe();
void DisplaySportShoe();
void DeleteSportShoe();
static void ExitSportShoe();
};
int SportShoe::MenuSportShoe() {
int OptionSportShoe = 0;
cout << endl;
cout << "Please select from the menu:" << endl;
cout << ":: 1 :: Add item to shoe list" << endl;
cout << ":: 2 :: Display shoes list" << endl;
cout << ":: 3 :: Delete item from the list" << endl;
cout << ":: 4 :: Back" << endl;
cout << "=>> ";
cin >> OptionSportShoe;
while (OptionSportShoe == 1){
AddSportShoe();
}
while (OptionSportShoe == 2){
DisplaySportShoe();
}
while (OptionSportShoe == 3){
DeleteSportShoe();
}
while (OptionSportShoe == 4){
ExitSportShoe();
}
return 0;
}
void SportShoe::AddSportShoe() {
nodeSport *tempShoe1, *tempShoe2;
tempShoe1 = new nodeSport;
cout << "Please enter the Shoe ID : (eg. 43210) " << endl;
cout << "=>> ";
cin >> tempShoe1->ShoeID;
cout << "Please enter the Shoe Brand: (eg. Adidas) " << endl;
cout << "=>> ";
cin.sync();
cin.getline(tempShoe1->BrandShoe,SIZE);
cout << "Please enter the Shoe Type : (eg. Running) " << endl;
cout << "=>> ";
cin.sync();
cin.getline(tempShoe1->TypeShoe,SIZE);
cout << "What is the Shoe Colour : (eg. Grey) " << endl;
cout << "=>> ";
cin.sync();
cin.getline(tempShoe1->ColourShoe,SIZE);
cout << "Please enter Shoe Size : (eg. 9) " << endl;
cout << "=>> ";
cin >> tempShoe1->SizeShoe;
cout << "Please enter the price of the Shoe : (eg. RM123.45) " << endl;
cout << "=>> RM ";
cin >> tempShoe1->PriceShoe;
tempShoe1->last = NULL;
if (first == NULL)
first = tempShoe1;
else
{
tempShoe2 = first;
while (tempShoe2->last != NULL)
tempShoe2 = tempShoe2->last;
tempShoe2->last = tempShoe1;
}
system("PAUSE");
MenuSportShoe();
}
void SportShoe::DisplaySportShoe() {
nodeSport *tempShoe1;
tempShoe1 = first;
while(tempShoe1){
cout << "ID : " << tempShoe1->ShoeID << endl;
cout << "Brand : " << tempShoe1->BrandShoe << endl;
cout << "Type : " << tempShoe1->TypeShoe << endl;
cout << "Colour : " << tempShoe1->ColourShoe << endl;
cout << "Size : " << tempShoe1->SizeShoe << endl;
cout << "Price : " << tempShoe1->PriceShoe << endl;
cout << endl;
tempShoe1 = tempShoe1->last;
}
system("PAUSE");
MenuSportShoe();
}
void SportShoe::DeleteSportShoe(){
nodeSport *tempShoe1, *tempShoe2;
int DataShoe;
tempShoe2 = tempShoe1 = first;
if(tempShoe1 == NULL)
{
cout << "\nList is empty!" << endl;
system("PAUSE");
MenuSportShoe();
}
while(tempShoe1 != NULL)
{
cout << "\nEnter the Shoes ID to be deleted: (eg. 123) ";
cin >> DataShoe;
tempShoe2 = tempShoe1;
tempShoe1 = tempShoe1->last;
if(DataShoe == tempShoe1-> ShoeID){
if(tempShoe1 == first) {
first = first->last;
cout << "\nData deleted ";
}
else{
tempShoe2->last = tempShoe1->last;
if(tempShoe1->last == NULL){
tempShoe2 = tempShoe2;
}
cout << "\nData deleted ";
}
delete(tempShoe1);
system("PAUSE");
MenuSportShoe();
}
else{
cout << "\nRecord not Found!!!" << endl;
system("PAUSE");
MenuSportShoe();
}
}
}
void SportShoe::ExitSportShoe(){
int sepatu;
cout << endl;
cout << "Please choose the option below."<<endl;
cout << ":: 1 :: Sport Shoe." << endl;
cout << ":: 2 :: Ladies High Heel." << endl;
cout << ":: 3 :: Exit" << endl;
cout << "=>> ";
cin >> sepatu;
while(sepatu == 1){
SportShoe listShoe;
listShoe.MenuSportShoe();
}
while(sepatu == 2){
HighHeel listShoe;
listShoe.MenuHighHeel();
}
while(sepatu == 3){
cout << "Thank you. Till we meet again."<< endl;
exit(1);
}
}
main() {
cout << "Hello! Welcome to MySepatu Online Shop administrator."<< endl;
cout << endl;
SportShoe::ExitSportShoe();
HighHeel::ExitHighHeel();
return 0;
}
public class linkedList {
int count = 0;
class Node {
int element;
Node next;
Node(int element) {
this.element = element;
}
}
Node head = null;
Node tail = null;
public void addNode(int Object) {
Node newNode = new Node(Object);
if (head == null) {
head = tail = newNode;
} else {
tail.next = newNode;
tail = newNode;
}
}
public void Display() {
Node current = head;
while (current!=null) {
System.out.println(current.element);
count ++;
current = current.next;
}
}
public void Length() {
System.out.println(count);
}
public void Remove(int node) {
Node curr = head;
while (curr!=null) { // looping the nodes
if (curr.element == node ) {
curr.element = curr.next.element;
curr = curr.next;
// To fix the Duplicates
while (curr!= tail) {
curr.element = curr.next.element;
curr = curr.next;
}
RemoveEnd();
break;
}
curr = curr.next;
}
}
public void RemoveEnd() {
Node current3 = head;
while (current3.next != tail) {
current3 = current3.next;
}
tail = current3;
tail.next = null;
}
}
I'm creating a database for school records for a project. I have a Student, Faculty, and Administrator class that all inherit things from a Person class. When I add the different objects to a Node, the information is stored in that Node (I see it via the debugger), however when I go to print a Node, I get
00266A88
instead of
Full Name: Reed
M Number: 999
Email:
and so on.
I'm just not sure what is causing the problem. Here is my method to print a node from the list:
template <typename T>
void TemplatedList<T>::printSpecific(int m_Number)
{
Node * Current = Head;
//If there is nothing in the list but the dummy head node, then return because there's nothing to print
if(Head->next == NULL)
{
cout << "Cannot print (M" << m_Number << "), NOT found!" << endl;
return;
}
else
Current = Current->next;
// While Current->next isn't equal to NULL, go through the list and see if the M-Numbers match. If they do, print the student and return
while(Current->next != NULL)
{
if(m_Number == Current->data->getM_Number())
{
cout << Current->data;
return;
}
else
{
Current = Current->next;
}
}
if(Current->next == NULL)
{
if(m_Number == Current->data->getM_Number())
{
cout << Current->data;
return;
}
else
{
cout << "Cannot print (M" <<m_Number << "), NOT found!" << endl;
return;
}
}
}
Here is the function to add one of the of the objects to the list:
template<typename T>
void TemplatedList<T>::addTemplatedList(T newAddition)
{
//Points to current node we're using
Node* Current = Head;
//Points to the node previous in the list to the current
Node* Previous = Head;
//Creates a new Node
Node* newNode = new Node;
//Assigns new Student information to new Node
newNode->data = newAddition;
// Check to see if the Head is only thing in the list. If it is, just place the new Node directly after the Head
if (Head->next == NULL)
{
Head->next = newNode;
newNode->next = NULL;
return;
}
else
{
while (Current->next != NULL)
{
if (newAddition->getM_Number() < Current->next->data->getM_Number())
{
newNode->next = Current->next;
Previous->next = newNode;
return;
}
else if (newAddition->getM_Number() == Current->next->data->getM_Number())
{
cout << "Person with M Number " << newAddition->getM_Number() << " not added because they are already in database." << endl;
delete newNode;
return;
}
Current = Current->next;
Previous = Previous->next;
}
if (Current->next == NULL)
{
Current->next = newNode;
newNode->next = NULL;
}
}
}
And finally here is how I'm calling the add function and creating a new object:
if (inputArray[0] == "A")
{
cout << "Adding Administrator: " << endl <<"\tFull Name:\t" << inputArray[1] << endl;
cout << "\tM Number:\t" << inputArray[2] << endl << "\tEmail Addr:\t" << inputArray[3] << endl << "\tTitle:\t " << inputArray[4] << endl;
Administrator *newAdmin = new Administrator;
istringstream stream (inputArray[2]);
int number;
stream >> number;
newAdmin->setAdmin(inputArray, number);
templatedList.addTemplatedList(newAdmin);
}
I would really appreciate and help that I can get because I'm just not sure what's happening or why it's giving me that incorrect output.
It looks like Node::data is a pointer to Administrator in this example. So when you do
cout << Current->data;
it merely outputs the pointer value. Assuming that you have implemented operator<< for the Administrator class, all you need to do is dereference:
cout << *Current->data;