linked list from the text file by words - c++

i wanted to read the text file by words and then apply each word for the linked list
but when i apply the whole content will goes to the first node of linked list
any idea what do i have to modify in the code
updated
i wander how can i iterate the word over the linked list i know i need another loop inside the while but i do not how do to it
it is build with C++
the file is working it showing by words but what i do not understand is how to take the words to be linked to each other
code:
#include <bits/stdc++.h>
#include <iostream>
#include<string>
using namespace std;
class LinkedList{
// Struct inside the class LinkedList
// This is one node which is not needed by the caller. It is just
// for internal work.
struct Node {
string x;
Node *next;
};
// public member
public:
// constructor
LinkedList(){
head = NULL; // set head to NULL
}
// destructor
~LinkedList(){
Node *next = head;
while(next) { // iterate over all elements
Node *deleteMe = next;
next = next->next; // save pointer to the next element
delete deleteMe; // delete the current entry
}
}
// This prepends a new value at the beginning of the list
void addValue(string val){
Node *n = new Node(); // create new Node
n->x = val; // set value
n->next = head; // make the node point to the next node.
// If the list is empty, this is NULL, so the end of the list --> OK
head = n; // last but not least, make the head point at the new node.
}
// returns the first element in the list and deletes the Node.
// caution, no error-checking here!
string popValue(){
Node *n = head;
string ret = n->x;
head = head->next;
delete n;
return ret;
}
// private member
private:
Node *head; // this is the private member variable. It is just a pointer to the first Node
};
int main() { //linkedlist
LinkedList list;
//string usama="usama";
//list.addValue(usama);
//list.addValue("h");
//list.addValue("u");
//cout << list.popValue() << endl;
//cout << list.popValue() << endl;
//cout << list.popValue() << endl;
// because there is no error checking in popValue(), the following
// is undefined behavior. Probably the program will crash, because
// there are no more values in the list.
// cout << list.popValue() << endl;
//file
// filestream variable file
fstream file;
string word, t, q, filename;
// filename of the file
filename = "file.txt";
// opening file
file.open(filename.c_str());
// extracting words from the file
while (file >> word)
{
list.addValue(word);
cout<<list.popValue()<<endl;
// displaying content
//cout << word << endl;
}
return 0;
}
i know maybe something wrong with the while loop but i am stuck at it

You have several problems. The first is popValue() does not handle the case where head == nullptr. This will likely cause a segfault when you attempt string ret = n->x; You can add a check on head and initialize ret to avoid this issue (the empty ret will be used to terminate the iteration later)
string popValue(){
Node *n = head;
string ret {};
if (!head) /* validate head not nullptr */
return ret;
ret = n->x;
head = head->next;
delete n;
return ret;
}
Next, as addressed in the comment, you use 1 loop to addValue and popValue. That defeats the purpose of your list because every node you add is deleted when you popValue() leaving your list empty at the end of the loop. Use 2 loops, e.g.:
// extracting words from the file
while (file >> word)
list.addValue(word);
while ((t = list.popValue()).length())
cout << t << '\n';
(note: (t = list.popValue()).length() terminates the iteration when an empty-string is reached -- better to have popValue() return a node instead of string.
A short working example taking the filename to read as the first argument would be:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class LinkedList {
struct Node {
string x;
Node *next;
};
public:
LinkedList(){
head = NULL; // set head to NULL
}
~LinkedList(){
Node *next = head;
while(next) { // iterate over all elements
Node *deleteMe = next;
next = next->next; // save pointer to the next element
delete deleteMe; // delete the current entry
}
}
void addValue(string val){
Node *n = new Node(); // create new Node
n->x = val; // set value
n->next = head; // make the node point to the next node.
// If the list is empty, this is NULL, so the end of the list --> OK
head = n; // last but not least, make the head point at the new node.
}
string popValue(){
Node *n = head;
string ret {};
if (!head) /* validate head not nullptr */
return ret;
ret = n->x;
head = head->next;
delete n;
return ret;
}
private:
Node *head; // this is the private member variable. It is just a pointer to the first Node
};
int main (int argc, char **argv) { //linkedlist
LinkedList list;
// filestream variable file
fstream file;
string word, t, q, filename;
// opening file
if (argc < 2)
return 1;
file.open(argv[1]);
if (!file.is_open()) {
cerr << "file open failed.\n";
return 1;
}
// extracting words from the file
while (file >> word)
list.addValue(word);
while ((t = list.popValue()).length())
cout << t << '\n';
return 0;
}
Example Input File
$ cat dat/captnjack.txt
This is a tale
Of Captain Jack Sparrow
A Pirate So Brave
On the Seven Seas.
Example Use/Output
$ ./bin/llwords dat/captnjack.txt
Seas.
Seven
the
On
Brave
So
Pirate
A
Sparrow
Jack
Captain
Of
tale
a
is
This
Lastly see Why is “using namespace std;” considered bad practice? and Why should I not #include <bits/stdc++.h>?

Related

how to avoid same input id value in c++

how to avoid double id in linked listed, example, i have id, name, gol, so firtst, i input id= 12, name=jon gol=A, when i input again. id=12, its show message "Id cant be same". input again can you help
this is my code for insert linked list first node,
#include <iostream>
#include <string>
#include <conio.h>
struct node {
int id;
char name[20], gol;
node *next;
};
node *head = nullptr;
node *tail = nullptr;
void tambah_awal_list() {
int id;
char name[20];
char gol;
node *baru = new node;
baru->id=head->id;
std::cout << "Id : ";
std::cin >> baru->id;
if (head->id == baru->id){
std::cout << "Id cant be same"<<std::endl;
}
std::cout << "Name : ";
std::cin >> baru->name;
std::cout << "Blood type (A/B/O) : ";
std::cin >> baru->gol;
if(head == nullptr) {
head = baru;
head->next = nullptr;
tail = head;
} else {
baru->next = head;
head = baru;
}
}
what should i change?
It depends on the spec and performance requirements.
If id could be decided by code instead of user input, then you just need to have an global counter increment every time a node is created.
You have to handle it carefully under multi-threading cases or very large number when number of nodes is out of range of int.
// Global variable or class member
int g_nextID = 0;
int generateID(){return ++g_nextID;}
void generate(){
node* n = new node();
n->id = generateID();
// ...
}
Use std::unordered_set<int> which takes O(1) time and O(N) space.
// A global variable or class member
std::unordered_set<int> g_used;
node *head = nullptr;
node *tail = nullptr;
void generate(){
// Inside the function
int id;
// Get user input into id
// ...
// Checking if used
if(g_used.find(id) == g_used.end()){
// Create the node
// ...
g_used.insert(id); // Save it
}else{
// Error handling.
}
}
void removeNode(int id){
// Remove it from list
// ...
// Remove it from set
g_used.erase(id);
}
Lookup the nodes, but it takes O(N) times.

C++ Singly Linked List Insertion Sort

So hey, I'm having a problem with this project I have. I'm supposed to read integers from a file and insert them into a list. There's a findSpot function that needs to be implemented that traverses the linked list and if the next node's value is larger than what is being checked, it returns the current "spot". And then we output the linked list to a separate file.
Here's the code.
#include <iostream>
#include <fstream>
using namespace std;
class listNode {
public:
int value;
listNode* next;
friend class linkedList;
listNode()
: value(0)
, next(NULL)
{
}
public:
~listNode(){
};
};
class linkedList {
listNode* listHead;
public:
linkedList()
: listHead(NULL)
{
}
bool isEmpty()
{
return (listHead == 0);
}
void listInsert(int data, listNode* spot)
{
listNode* newNode;
newNode->value = data;
newNode->next = NULL;
if (isEmpty()) {
listHead = newNode;
}
else {
newNode->next = spot->next;
spot->next = newNode;
cout << newNode;
}
}
/*void listDelete ()
{
}*/
listNode* findSpot(int data)
{
listNode* spot;
spot = listHead;
while (spot->next != 0 && spot->next->value < data) {
spot = spot->next;
}
return spot;
}
void printList(listNode* spot)
{
listNode* newNode = spot;
while (newNode != NULL) {
cout << "Inserting " << newNode->value << ": "
<< "listHead-->(" << newNode->value << "," << newNode->next->value << ")-->(";
newNode = newNode->next;
}
cout << endl;
}
/*~linkedList()
{
listNode* temp = spot->next;
spot->next = spot->next->next;
delete temp;
}*/
};
int main(int argc, char* argv[])
{
int data;
listNode* spot;
ifstream infile;
infile.open(argv[1]);
ofstream outfile(argv[2]);
cout << "Reading Data from the file" << endl;
while (infile >> data) {
cout << data << endl;
}
infile.close();
linkedList myList;
infile.open(argv[1]);
while (infile >> data) {
myList.findSpot(data);
myList.listInsert(data, spot);
myList.printList(spot);
}
cout << "Printing your linked list to the output file.";
/*while (outfile.is_open())
{
myList.printList();
}*/
infile.close();
outfile.close();
return 0;
}
I don't know if the problem lies mainly in the insertList function or if it's the findSpot function. The findSpot function seems correct to me but I may just be missing something.
As I run the code, the actual reading of the file the first time is fine. Actually inserting anything into the linked list causes the program to hang.
Ok, lets try this again. I'll actually include some code, but please try to use this as a learning point, and not something to just copy paste. I know you said you were copying your teachers algorithm, but what they gave you is probably just that, an algorithm. It is your job to actually implement that in working code, checking for error conditions, etc. Anyway, here we go:
For the function findSpot:
listNode* linkedList::findSpot(int data) {
listNode* spot = listHead; // Initialize spot to start of list
if ( isEmpty() ) // if list is empty, return NULL
return NULL;
// now we know listHead isn't null, so look through the list and
// find the entry that has a value greater than the one provided
// return the list item BEFORE the one with the greater value
while (spot->next != 0 && spot->next->value < data) {
spot = spot->next;
}
// return the one we found; This could be the same as listHead
// (start of list), something in the middle, or the last item on the
// list. If we return from here, it will not be NULL
return spot;
}
Now we can do the insert function:
void linkedList::listInsert(int data, listNode* spot) {
// We need a new item to put on the list, so create it
listNode* newNode = new listNode();
newNode->value = data;
newNode->next = NULL;
// If the list is empty, update the head to point at our new object
if ( isEmpty() ) {
listHead = newNode;
// otherwise point spot to new item, and new item to the one spot
// pointed to
} else {
newNode->next = spot->next;
spot->next = newNode;
}
}
Looking at your print function, that is going to have it's own issues. It looks like you want to print the whole list, but it seems that you are starting to print from "spot". It's all very confused. It also has an issue using newNode->next->value, without checking if newNode->next is NULL. Here's a short example of what I think you are trying to do... note that I don't even need to pass in spot, just the data point added:
void linkedList::printList(int data) {
// if some huckleberry called this before calling insert,
// list will be empty... always a good idea to check
if ( isEmpty())
return;
// first line of output... just print out the data point
// added and start of output text
cout << "Inserted " << data << ": " << "listHead-->(";
// start at start of list
listNode* newNode = listHead;
// loop through until we find the end
while (newNode != NULL) {
cout << newNode->value; // print the value
newNode = newNode->next; // move to the next item on the list
// We moved to the next node; It might be NULL and the loop will end
// if not, we want to print an open bracket since we know another one
// is going to be printed
if ( newNode != NULL )
cout << ")-->(";
}
// last item was just printed, so close off the last bracket
cout << ")" << endl;
}
Hope that is somewhat helpful
Since this looks like a homework assignment, I'm going to give you one fix:
change
myList.findSpot(data);
to
spot = myList.findSpot(data);
If you look closely, spot is used, but never assigned anything.
Well, there are several problems with your program (besides formatting). In the function findSpot(), you have:
listNode* spot;
spot = listHead;
while (spot->next != 0 && spot->next->value < data) {
spot = spot->next;
}
return spot;
The problem here is that the first time you call this, listHead is NULL, so the
while (spot->next
is going to fail, since spot is NULL.
I also notice that nowhere in your code do you call new(). In listInsert, you need to use new() to initialize your newNode variable.
Lastly, find spot has 2 conditions where it can return NULL. If the list is empty, it should return NULL, and you would want to insert at the start of the list. If the new value you are adding is greater than all the others, you will also return NULL and you would have to add to the end of the list.
Since this is a homework assignment, I don't want to write the code for you, but hopefully that helps.

How to dynamically create new nodes in linked lists C++

Could anyone tell me if this is the basic idea of linked lists? What are the pros and cons to this method and what are best practices when implementing linked lists in C++? Im new to data structures so this is my first approach. If there is a better way to do this same thing, please let me know. Additionally, how would you create the nodes dynamically without hard coding it? Thanks.
#include <iostream>
#include <string>
using namespace std;
struct node {
int x;
node *next;
};
int main()
{
node *head;
node *traverser;
node *n = new node; // Create first node
node *t = new node; // create second node
head =n; //set head node as the first node in out list.
traverser = head; //we will first begin at the head node.
n->x = 12; //set date of first node.
n->next = t; // Create a link to the next node
t->x = 35; //define date of second node.
t->next = 0; //set pointer to null if this is the last node in the list.
if ( traverser != 0 ) { //Makes sure there is a place to start
while ( traverser->next != 0 ) {
cout<< traverser->x; //print out first data member
traverser = traverser->next; //move to next node
cout<< traverser->x; //print out second data member
}
}
traverser->next = new node; // Creates a node at the end of the list
traverser = traverser->next; // Points to that node
traverser->next = 0; // Prevents it from going any further
traverser->x = 42;
}
for tutorial purpose, you can work out this example:
#include <iostream>
using namespace std;
struct myList
{
int info;
myList* next;
};
int main()
{
//Creation part
myList *start, *ptr;
char ch = 'y';
int number;
start = new myList;
ptr = start;
while (ptr != NULL)
{
cout << "Enter no. ";
cin >> ptr->info;
cout << "Continue (y/n)? ";
cin >> ch;
if (ch == 'y')
{
ptr->next = new myList;
ptr = ptr->next;
}
else
{
ptr->next = NULL;
ptr = NULL;
}
}
//Traversal part begins
cout << "Let's start the list traversal!\n\n";
ptr = start;
while (ptr!=NULL)
{
cout << ptr->info << '\n';
ptr = ptr->next;
}
}
It allocates memory dynamically for as many elements as you want to add.
I'd prefer to make a linked list class. This eliminates the need to call 'new' more than once. A nice implementation with examples can be found here.
You are in fact already doing dynamic allocation. So, not sure what you are asking for. But if you want to define functions to add new nodes to your linked list (or delete a node etc.), this can be a probable solution:
The location nodes get inserted/deleted is dependent on the type of data-structure. In a queue, new nodes will get added to the end; at the top in case of a stack. A function that adds a node to the top, simulating STACK push operation:
void pushNode(node **head, int Value) {
node *newNode = new node;
newNode->x = Value;
newNode->next = *head;
*head = newNode;
}
It would be called like pushNode(&head, 15) where 'head' would be defined as node *head = NULL. The root head should initially be set to NULL. After this operation head will point to the newly added node (top of stack).
The approach would be very similar for other data-structures (viz. queues) and works fine. But as you are using C++, I would suggest to define a class for your linked-list and define these functions as methods. That way, it will be more convenient and less error-prone.
Even better use std::list. It's the standard thing, so much portable and robust than a custom implementation.
You can also do it in this way
#include <iostream>
using namespace std;
struct Node{
int data;
Node* next;
};
void createList(Node** head ,Node* temp){
int n;
char ch;
temp = *head;
while(temp != NULL){
cout<<"Enter The Value ";
cin>>temp->data;
cout<<"DO you want to continue(y/n)";
cin>>ch;
if(ch=='Y' || ch == 'y'){
temp->next = new Node;
temp = temp->next;
}else{
temp->next = NULL;
temp = NULL;
}
}
}
void ShowList(Node* head){
cout<<"your list :"<<endl;
while(head != NULL){
cout<<head->data<<" ";
head = head->next;
}
}
int main()
{
//Creation part
Node *head, *temp;
createList(&head,temp);
ShowList(head);
}

C++ unhandled exception. 0xC0000005: Access violation reading location 0xccccccd0

I have been trying to work through this for the past couple of hours by going through my call stack, and have still yet to figure out what is going on!
My Sequence Database that basically gathers the info needed from a file, then calls on my Linked List class to create a new node with the gathered info, and put that node at the end of the Linked List:
Header:
#ifndef SEQUENCE_H
#define SEQUENCE_H
#include "DNA.h"
#include "DNAList.h"
class SequenceDatabase
{
public:
//Default Constructors
SequenceDatabase();
//Methods
void importEntries(string);
private:
DNAList list;
};
#endif
Source:
#include "SequenceDatabase.h"
#include "DNA.h"
#include "DNAList.h"
#include <fstream>
using namespace std;
SequenceDatabase::SequenceDatabase() //Default Constructor.
{
DNA object;
DNAList list;
}
void SequenceDatabase::importEntries(string name)
{
DNA* item;
ifstream file;
file.open(name);
if(!file.is_open())
{
cout << "Error opening file!" << endl;
exit(1);
}
char letter;
string label, sequence;
int ID, length, index;
file >> letter;
if(letter == 'D' || letter == 'd')
{
file >> label >> ID >> sequence >> length >> index;
DNA object(label,ID,sequence,length,index);
item = &object;
DNAList list(item);
}
}
My Linked List Header file:
class DNAList
{
public:
//Constructors
DNAList();
DNAList(DNA* newDNA);
//Linked List Functions
void push_back(DNA* newDNA);
DNA* findID(int ID);
void obliterate(int ID);
//DNANode struct for Linked List
struct DNANode
{
DNA* data;
DNANode* next;
DNANode* prev;
};
private:
DNANode* head;
typedef DNANode * ptr;
};
#endif
My Linked List class source file:
#include "DNAList.h"
#include "SequenceDatabase.h"
#include "DNA.h"
#include <iostream>
using namespace std;
DNAList::DNAList()
{
head = NULL;
}
DNAList::DNAList(DNA* newDNA)
{
cout <<"In DNA list second constructor" << endl;
ptr cur;
if(head == NULL)
{
ptr newNode = new DNANode;
cur = newNode;
cur -> data= newDNA;
head = cur;
cur -> prev = head;
cur -> next = NULL;
}
else
{
push_back(newDNA);
}
}
void DNAList::push_back(DNA* newDNA)
{
ptr cur;
ptr last;
cout << "Note: Adding " << newDNA -> getID() << " ..." << endl;
ptr newNode = new DNANode;
cur = head;
while(cur != NULL)
{
last = cur;
cur = cur -> next; //ERROR IS HAPPENING AT THIS LINE.
}
newNode -> data = newDNA;
newNode -> prev = last;
newNode -> next = NULL;
cur = newNode;
}
Now, I am new to using classes to contain my linked lists, so I am not sure if my node struct should be in public or private memory for my Linked List class, and also if my constructors are defined the way they should be. The Node struct is basically a pointer to the actual data that is in a header file called DNA with additional pointers to the struct for my next and previous Nodes so that the data is never messed with, but just pointed to.
The error is being stuck on the line right in the middle of my push_back function in my Linked List source file. I labeled it appropriately. Please can someone share some insight on what I am doing wrong here? Thanks!
My main file:
#include <iostream>
using namespace std;
#include "sequenceDatabase.h"
int main(){ //int argc, char* argv[]){
string commandsFileName;
commandsFileName = "lab1-commands-short.tab"; // for initial development
//commandsFileName = "lab1-commands.tab";
// commandsFileName = "lab1-commands-test.tab"; // for testing & grading
SequenceDatabase entries;
cout << "Importing " << commandsFileName << endl;
entries.importEntries(commandsFileName);
return 0;
}
if (...)
{
DNA object(label, ID, sequence, length, index);
item = &object;
DNAList list(item);
}
object is a locally-scoped object, meaning it is destroyed at the ending brace of the block. You're setting item to point to that local object and sending if off to the constructor of DNAList. The problem with that is if you try to access object after it has been destroyed, your program will no longer be in a valid state. This is because once your object is destroyed, the object that pointed to it will be left as a dangling pointer. Things like accessing a dangling pointer is known as Undefined Behavior.
But that's not where your UB comes from (yet). The real problem is in your DNAList constructor:
if (head == NULL)
{
// ...
}
else
{
push_back(newDNA);
}
head is an uninitialized pointer. Primitive objects (like int, char, char*) that are declared but not defined are uninitialized and thus have an indeterminate value. Testing objects in this state as if they had a value is also Undefined Behavior.
Note that UB can still appear to make your code work properly. But it can also do other nasty things that make no logical sense in your program.
head has the value of whatever was stored in the stack at that moment, which probably wasn't 0. So the condition fails and push_back() is invoked.
Then you do cur->next inside the while loop which dereferences an uninitialized pointer, finally causing an exception to be thrown.
That particular runtime error could be avoided by setting head to NULL inside the constructor body of DNAList and dynamically allocating object (so that it exists beyond the scope of the if statement, but there are still a few more things that are not right in your program as specified in the comments.

Deleting Node in Linked List C++

So I've been searching forums, but im still very new to the language and linked lists so I can barely decipher the results.
basically I made a delete function for my linked list.
I can currently Create a list, traverse the list, sort the list, search the list, and insert before any node in the linked list. I recycled some code from the insert to locate the point in the list where I could delete. My main point of confusion is how to link the previous points to the node that is after the one I am deleting.
I won't write a whole new linked list implementation but i can point out some of the problems with the code for you.
The trick is to stay one node ahead of the one you want to delete.
I have renamed entry to current for clarity
nodetype *current , *first, *next;
int akey;
// With this line your search will start from the second element.
// current =start->ptr;
// Should be
current = start;
// this is not needed. I am assuming the last node has NULL value for '->ptr'
// last=start;
next = current->ptr;
cout<<"Input Data You Would Like To Delete"<<endl;
cin>>akey;
// Check if the first node contains the data
// Assuming the list will have at least one element. i.e. current is not NULL
while (current->adata == akey)
{
// Delete it.
delete current;
// Update current for the while loop
current = next;
// update next too.
next = current->ptr;
}
// Now we know the first element doesn't contain the data.
// Update the pointer to the begging of the new list if anything is removed from the top.
first = current;
// This has unnecessary checks.
// ****Specifically (akey!=current->adata) will
// prevent you from entering the loop if it is false.
// while((akey!=current->adata)&&(current->ptr !=NULL))
while(next != NULL) // This should be enough
{
if(next->adata == akey)
{
// make the current node (before the 'deletion point')
// lined to the one after the 'deletion point (next of the next)
current->ptr = next->ptr;
// delete the node.
delete next;
// Make the next pointer point to the new next.
next = current->ptr
}
// Otherwise advance both current and next.
else {
current = next;
next = next->ptr;
}
}
// Use this to test it.
current = first;
while(current){
cout<<current->adata<<", ";
current = current->ptr;
}
This is not the cleanest way. However it is similar to your implementation so you can see where you went wrong.
#include <iostream>
#include <string>
// blank line(s) after includes
using namespace std; // some people will say to avoid this
// but I use it in examples for brevity
// blank line(s) around class def
class nodetype
{ // bracket on its own line
public: // non indented visibility specifier
nodetype(int value, nodetype *p) // constructor first declared in class
{
adata = value; // level of indentation for fn body
ptr = p; // spaces around operators like =
}
// blank line(s) between fns and vars
int adata;
nodetype *ptr;
};
// blank line(s) between class and fn
void LinkedListDelete(nodetype **start, int akey)
{
nodetype *current, **previous; // pointer *s are connected to vars
// blank line between section
previous = start;
current = *start;
// blank line between section
// I use blank lines a lot, they help
// me to organize my thoughts
while((current != NULL) && (akey != current->adata))
{ // indentation inside nested scope
previous = &current->ptr; // no space for unary operators like &
current = current->ptr; // assignments justified to same level
}
if (current != NULL)
{
*previous = current->ptr; // no space for unary *, space for =
delete current;
}
// more blank lines between sections
return;
}
void LinkedListPrint(nodetype *list) // no space for unary *
{ // brackets on their own lines
while (list != NULL) // space around !=
{
cout << "(Node: " << list->adata << ") ";
list = list->ptr; // spaces around <<
}
cout << endl;
}
int main()
{
nodetype *node = new nodetype(5, new nodetype(10, // justified stuff
new nodetype(7, new nodetype(14,
new nodetype(23, NULL)))));
// blank lines
cout << "Build linked list: ";
LinkedListPrint(node);
cout << "Removed node 7: ";
LinkedListDelete(&node, 7);
LinkedListPrint(node);
return 0;
}
I made this code based on the code you provided. It's not quite the same, I changed some things, but it does what you want it to. I had to guess what the structure of nodetype was, and I added a constructor for my convenience. I added some comments pointing out aspects of my style.
Notice that it's easier to read than the code you originally provided. Style is important. People will tell you that you have to use X or Y style, but what really matters is that you pick whatever style you like and stick to it consistently; it will make it easier for you to read and understand your own code quickly.
Believe me you, when you've written a lot of code, you stop being able to remember all of it at once, and being able to figure out what you were doing quickly is essential.
Consider the structure given below,
struct info
{
int data;
struct info *next;
};
if you use the above structure to store records in your linked list, then the following code can be used to delete elements from your linked list,
void delitem()
{
info *curr,*prev;
int tdata;
if(head==NULL)
{
cout<<"\nNo Records to Delete!!!";
}
cout<<"\nEnter the Data to be deleted: ";
cin>>tdata;
prev=curr=head;
while((curr!=NULL)&&(curr->data!=tdata))
{
prev=curr;
curr=curr->next;
}
if(curr==NULL)
{
cout<<"\nRecord not Found!!!";
return;
}
if(curr==head)
{
head=head->next;
cout<<"\nData deleted: "<<tdata;
}
else
{
prev->next=curr->next;
if(curr->next==NULL)
{
temp=prev;
}
cout<<"\nData deleted: "<<tdata;
}
delete(curr);
}
I think it is too simple and easy to delete a node or insert ine in linked-list but it requires precise understanding of its MECHANISM. this example shows how to add and remove nodes however it is not a full program but it reveals the mechanism of adding and deleting and moving alinked-list:
#include <iostream>
using namespace std;
//class Data to store ages. in a real program this class can be any other
//class for example a student class or customer...
class Data
{
public:
Data(int age):itsAge(age){}
~Data(){}
void SetAge(int age){itsAge=age;}
int getAge()const{return itsAge;}
private:
int itsAge;
};
//the most important part of the program is the linked0list
class Node
{
public:
//we just make itsPtrHead when created points to Null even if we pass a pointer to Data that is not NULL
Node(Data* pData): itsPtrData(pData),itsPtrHead(NULL),itsCount(0){}
Data* getPdata()const;
Node* getPnext()const;
int getCount()const{return itsCount;}
void insertNode(Data*);//import bcause it shoes the mechanism of linked-list
void deleteNode(int);//most significant in this program
Data* findData(int&,int);
void print()const;
private:
Data* itsPtrData;
Node* itsPtrHead;
int itsCount;
};
Data* Node::getPdata()const
{
if(itsPtrData)
return itsPtrData;
else
return NULL;
}
Node* Node::getPnext()const
{
return itsPtrHead;
}
void Node::insertNode(Data* pData)
{
Node* pNode=new Node(pData);//create a node
Node* pCurrent=itsPtrHead;//current node which points first to the first node that is the "head bode"
Node* pNext=NULL;//the next node
int NewAge=pData->getAge();//the new age that is past to insertNode function
int NextAge=0;//next age
itsCount++;//incrementing the number of nodes
//first we check wether the head node "itsPtrHead" points NULL or not
//so if it is null then we assign it the new node "pNode" and return from insert function
if(!itsPtrHead)
{
itsPtrHead=pNode;
return;
}
//if the condition above fails (head is not null) then check its value and
//compare it with new age and if the new one is smaller than the head
//make this new one the head and then the original node that head points to it make it its next node to the head
if(itsPtrHead->getPdata()->getAge() > NewAge)
{
pNode->itsPtrHead=itsPtrHead;
itsPtrHead=pNode;
//exit the function
return;
}
//if the condition above fails than we move to the next node and so on
for(;;)
{
//if the next node to the current node is null the we set it with this new node(pNode) and exit
if(!pCurrent->itsPtrHead)
{
pCurrent->itsPtrHead=pNode;
return;
}
//else if it not null(next node to current node)
//then we compare the next node and new node
pNext=pCurrent->itsPtrHead;
NextAge=pNext->getPdata()->getAge();
//if next node's age is greater than new then we want new node
//to be the next node to current node then make the original next to current to be the next to its next
if(NextAge > NewAge)
{
pCurrent->itsPtrHead=pNode;
pNode->itsPtrHead=pNext;
//exitting
return;
}
//if no condition succeeds above then move to next node and continue until last node
pCurrent=pNext;
}
}
// delete a node is a bit different from inserting a node
void Node::deleteNode(int age)
{
//deleting a node is much like adding one the differecne is a bit trickier
Node* pTmp=itsPtrHead;
Node* pCurrent=itsPtrHead;
Node* pNext=NULL;
//1 checking for wether age (node contains age) to be deleted does exist
for(;pTmp;pTmp=pTmp->itsPtrHead)
{
if(pTmp->getPdata()->getAge() == age)
break;
}
//if age to be deleted doesn't exist pop up a message and return
if(!pTmp)
{
cout<<age<<": Can't be found!\n";
return;
}
int NextAge=0;
for(;;)
{
//if age to be deleted is on the head node
if(itsPtrHead->getPdata()->getAge() == age)
{
//store the next to head node
pTmp=itsPtrHead->itsPtrHead;
//delete head node
delete itsPtrHead;
//assign the head new node (node after the original head)
itsPtrHead=pTmp;
//decrement the count of nodes
itsCount--;
//exiting gracefully
return;
}
//moving to next node
pNext=pCurrent->itsPtrHead;
NextAge=pNext->getPdata()->getAge();
//checking next node age with age to be deleted. if they
//match delete the next node
if(NextAge == age)
{
//next node holds the target age so we want its NEXT node
//and store it in pTmp;
pTmp=pNext->itsPtrHead;//Next node of the target node
//pCurrent doesn't yet hold the target age but it is the
//previous node to target node
//change the next node of pCurrent so that it doesn't
//point to the target node but instead to the node right
//after it
pCurrent->itsPtrHead=pTmp;
//delete the target node (holds the target age)
delete pNext;
//decrement number of nodes
itsCount--;
//exit
return;
}
//if pNext doesn't point to target node move to the next node
//by making pCurrent points to the next node in the list
pCurrent=pNext;
}
}
void Node::print()const
{
Node* pTmp=itsPtrHead;
while(pTmp)
{
cout<<"age: "<<pTmp->getPdata()->getAge()<<endl;
pTmp=pTmp->itsPtrHead;
}
}
int main()
{
//note this is not a real proram just we show how things works
Data* pData=new Data(6);
Node theNode(pData);
theNode.print();
pData=new Data(19);
theNode.insertNode(pData);
pData=new Data(20);
theNode.insertNode(pData);
pData=new Data(23);
theNode.insertNode(pData);
pData=new Data(25);
theNode.insertNode(pData);
pData=new Data(30);
theNode.insertNode(pData);
pData=new Data(27);
theNode.insertNode(pData);
pData=new Data(33);
theNode.insertNode(pData);
pData=new Data(18);
theNode.insertNode(pData);
theNode.print();
cout<<endl<<endl;
//int age;
//int index;
//cout<<"Age to finde: ";
//cin>>age;
//cout<<endl;
//theNode.Find(index,age);
//cout<<age<<" : Found on index: "<<index<<endl;
//theNode.modify(age);
//theNode.print();
int age;
cout<<"age to delete: ";
cin>>age;
cout<<endl;
theNode.deleteNode(age);
theNode.print();
cout<<endl<<endl<<endl;
return 0;
}
//modify and other member functions are not the purpose of this program
void Delete()
{
int num;
cout<<"enter node to delete"<<endl;
cin>>num;
node *nodeptr=head;
node *prev;
if(head==0)
{
cout<<"list is empty"<<endl;
}
else if(head->data==num)
{
node *t=head;
head=head->next;
delete t;
}
else
{
nodeptr=head;
prev=head;
while(nodeptr!=NULL)
{
if(nodeptr->data==num)
{
prev->next=nodeptr->next;
node *tem=nodeptr->next;
delete tem;
}
prev=nodeptr;
nodeptr=nodeptr->next;
}
}
}