I'm trying to print the alphabet backwards using linked lists but I can't get the 'a' to show up. For some reason it skips it and I can't figure it out. Here is my code:
int _tmain(int argc, _TCHAR* argv[])
{
char s[]="abcdefghijklmnopqrstuvwxyz";
node *head;
node *temp;
node *current;
head = new node; // create the head of the linked list
head->data = s[25];
head->next = NULL;
temp = head; // get ready for the loop - save the head in temp - you are going to change temp in the loop
for(size_t i = 25; i >= 1; i--) // create the rest of the linked list
{
current = new node; // make a new node
current->data = s[i]; // set it's data member
current->next = NULL;
temp->next = current; // point to the new node
temp = current; // make temp point to current node (for next time through)
}
node *ptr = head; // set a ptr to head, then you are going to "increment" the pointer
while (ptr != NULL)
{
cout << ptr->data; // print out the linked list
ptr = ptr->next; // increment the linked list
}
cout << endl;
system("pause");
return 0;
}
does anyone know why it's happening? I think something is wrong in my for loop. Thank you!
The problem is that you are leaving out the case i=0 from your for loop.
Change your for loop to this:
size_t i = 25; // 'z' was already added
do
{
--i;
current = new node; // make a new node
current->data = s[i]; // set it's data member
current->next = NULL;
temp->next = current; // point to the new node
temp = current; // make temp point to current node (for next time through)
} while ( i != 0 );
The reason you can't simply do for(size_t i = 25; i >= 0; i--) is because i is unsigned, and so it will always be the case that i >= 0 and thus the loop will never terminate, or more likely you will get a segmentation fault.
for(size_t i = 25; i >= 0; i--)
'a' is the index 0 in your string, you never get to index 0.
Related
void LinkedList::insert(int num, int pos) {
Node *newNode = new Node;
newNode->data = num;
newNode->next = NULL;
if(pos == 0) {
newNode->next = head;
head = newNode;
}
else {
Node *temp = head;
for (int i = 1; i < pos-1; ++i) {
if (temp != NULL) {
temp = temp->next;
}
}
if (temp != NULL) {
newNode->next = temp->next;
temp->next = newNode;
}
else {
cout << " The previous node is full.";
}
}
}
This is my insert function.
The code that runs in main.cpp is:
// adding through insert
nums.insert(1, 0);
nums.insert(5, 4);
nums.insert(3, 7);
And the output is:
List after append:
8 6 7 8 0 9
List after inserting:
1 8 6 5 7 8
As you can see, something is getting overwritten, or the end of the list just gets cut off. I have searched the internet for hours to no avail. The output needs to increase the length of the list and not overwrite anything. Any help would be appreciated.
The problem is this for loop
for (int i = 1; i < pos-1; ++i) {
if (temp != NULL) {
temp = temp->next;
}
}
Let's assume that pos is equal to 2. In this case the loop will not iterate and temp will be equal to head. So the new node will be inserted before the second mode instead to be inserted before the third node.
You need to write
for (int i = 1; temp != nullptr && i < pos; ++i) {
temp = temp->next;
}
Also instead of writing this message
cout << " The previous node is full.";
(it is the caller of the function should decide whether to output a message) I would declare the function like
bool LinkedList::insert(int num, int pos) {
and return either true or false dependent on whether a node was inserted.
I have a problem, I am trying to create a list that deletes a highest value holding number, or all numbers with the same value if the value is highest in the list. Thank you for any kind of tips.
// n,n1,head,next - are pointers
int j = 0; //this number helps to put pointer forward by one place
while(n!=0){//should go through every digit of the list
if(head == 0){
cout << "list is empty" << endl;
}
else{
n = head;
n1=0; // n1 and n are pointers
while(n!=0){
if(n->sk == maxx){//searches for maximum digit in the list
break;
}
else{
n1=n;
n=n->next;
}
}
if(head == n){
head = head->next;
}
else{
n1->next = n->next;
}
delete n; // deletes the pointer holding the highest value
}
n = head; //problem is here or somewhere below
j++;
for(int i=0; i<j;i++){ // this loop should make the pointer point to the first
n = n->next; // number, then the second and so on until the end of list
} // and all the numbers inside the list with the value that
} // equals "maxx" should be deleted
You should dereference the pointers. Right now, you're pointing to their addresses. See if that helps resolve your problem.
Ok, the problem (the most of it) is the code:
while(n!=0){
if(n->sk == maxx){
break;
}
else{
n1=n;
n=n->next;
}
}
If you find the maxx value you should delete that node and continue to searching, don't break. This way you don't need so much code for this task.
while (n != 0){
if (n->sk == maxx){
node *prev = n->prev; // The previous node.
node *tmp = n; // this assume you have a class node.
// temporaly holds the pointer to n.
prev->next = n->next; // Connect the previous node with the following one.
n = n->next; // advance n to the next node in the list.
delete tmp; // delete the node.
}
}
If I understand correctly what you want, you can just iterate over your list and save the pointer for deletion:
it = head;
pos = nullptr;
while (it != nullptr) {
if(it -> sk == maxx) {
pos = it; // save ptr
it = it -> next;
delete pos; // delete saved ptr
pos = nullptr;
}
}
I'm writing code that takes integers that are input from the user and creates a linked list and then prints out the list. However, when I enter values 1,2,3,4,5, the output is only 5 5 5 5 5
Please tell me where am i wrong here.
The code is as follows:
include"iostream"
using namespace std;
struct node
{
int number;
node* next;
};
int main()
{
node* head;
head = NULL;
int i,n,x;
cin>>n;
cout<<endl;
for(i=0;i<n;i++)
{
cin>>x;
//Insert(x);
node* temp;
temp = new node;
temp->number = x;
temp->next = NULL;
head = temp;
}
//Print();
node* temp;
temp = head;
while(temp != NULL)
{
for(int j=0; j<n; j++)
cout<<temp->number<<" ";
temp = temp->next;
}
}
Remember that when setting the head pointer, you should only do so when the list is empty (i.e when head == NULL). We should do this after we create the new node so we know what to set head to:
node* temp = new node;
temp->number = x;
temp->next = NULL;
if (head == NULL) // if the list is empty then...
head = temp; // temp is the start of the list
There's also another problem. temp is supposed to be added to the end of the list each time it's created. If the list is empty then head is the end of the list, but if the list already has elements then we need to go to the end and set the next pointer of that node to temp. This is fairly straightforward, all it takes is a while loop to iterate over the list to the end:
if (head == NULL)
head = temp;
else // the list is not empty
{
// so we need to go to the end
node* p = head;
while (p->next != NULL)
p = p->next; // keep going through
// p now points to the last node
p->next = temp;
}
There's also the option of keeping a prev node that points to the last element inserted. This makes it so that we don't have to go through the list each time to find the end:
node* head = NULL, prev = NULL;
for (/* ... */)
{
// ...
if (head == NULL)
head = prev = temp;
else
{
prev->next = temp;
prev = temp;
}
}
The last thing is the way you're printing. You shouldn't have a nested for loop here:
while (temp != NULL)
{
for(int j = 0; j < n; j++)
cout << temp->number << " ";
temp = temp->next;
}
Taking it out will make it print correctly.
This looks a bit wrong:
while(temp != NULL)
{
for(int j=0; j<n; j++)
cout<<temp->number<<" "; // Only this is part of the for() loop
temp = temp->next; // This happens after the for() loop ends
}
Only the first line gets executed by the for() loop so it keeps outputting the same number. Why is the for loop there anyway? What is it supposed to do?
Try this:
while(temp != NULL)
{
cout<<temp->number<<" ";
temp = temp->next;
}
See if that works better.
ALSO:
As #crashmstr pointed out your insert logic is wrong:
for(i=0;i<n;i++)
{
cin>>x;
//Insert(x);
node* temp;
temp = new node;
temp->number = x;
temp->next = NULL; // this should point to the nextnode
head = temp;
}
Try:
for(i=0;i<n;i++)
{
cin>>x;
//Insert(x);
node* temp;
temp = new node;
temp->number = x;
temp->next = head; // the current begining
head = temp;
}
*ALSO 2:
include"iostream" // not right
Please use:
#include <iostream> // correct!
I'm trying to delete the n'th element, which is a random number from 1 to n.
My code does this fine (correct element is deleted and surrounding elemnts are connected) but when it comes to being efficient, it is crashing when I un-comment the line delete (nodeToRemove); and I'm not sure why. Does anyone have any insight?
Assuming my struct looks like :
struct Node {
int data; // The data being stored at the node
Node *next; // Pointer to the next node
};
//------------------------------------------------------------------------------
void deleteNthElement (Node * & head, Node * &temp, int random)
{
temp = head;
Node *nodeToRemove;
if (random == 1)
{
nodeToRemove = temp;
head = head->next;
}
else
{
for (int i = 1; i < random - 1; i++)
temp = temp->next;
nodeToRemove = temp->next;
temp->next = temp->next->next;
}
// delete (nodeToRemove); <----- uncommenting this leads to crash,
}//end deleteNthElement()
//------------------------------------------
int main()
{
Node *head = NULL;
Node *temp;
Node *listarray[n[i]];
int n[] = {1000, 5000, 9000, 105000, 400000, 500000, 505000, 800000, 995000, 1000000};
for (int j = 0; j < n[i]; j++)
listarray[j] = new (Node);
//start timer
begin = clock();
//fill it
for (int j = 0; j < n[i]; j++)
{
listarray[j]->data = (rand() % n[i] + 1);
insertNodeInOrder (head, temp, listarray[j]);
}
//delete it
for (int j = 0; j < n[i]; j++)
deleteNthElement (head, temp, (rand() % (n[i] - j) + 1));
//deallocate
for (int j = 0; j < n[i]; j++)
delete listarray[j];
delete *listarray;
//end timer
}
You're picking the wrong Node, you want:
...
nodeToRemove = temp;
...
At least, you have to check for the end of the list, that is, you need to avoid access to null pointers (i really hope you set next to 0 at the end of the list). If you add the allocation parts, I will extend my answer.
void deleteNthElement (Node * & head, Node * &temp, int random)
{
temp = head;
Node *nodeToRemove;
if (random == 1)
{
nodeToRemove = temp;
if(head != 0)
head = head->next;
} else {
for (int i = 1; i < random - 1; i++)
if(temp != 0)
temp = temp->next;
else throw 1; // no such index; throw something more verbose :)
if(temp == 0)
throw 1; // same situation as above
nodeToRemove = temp->next;
if(nodeToRemove == 0)
throw 1; // same situation as above
temp->next = temp->next->next;
}
if(nodeToRemove == 0)
throw 1; //no such index; ... as the above 3
delete nodeToRemove;
}//end deleteNthElement()
Some clean-up first:
Why pass in two pointers here? do you need the value of temp out? If so why not return it?
Also why the node * & temp? (I can see why it is done for head).
int random should probably be called something like index as it describes the functionality better (as far as the function is concerned, there is nothing random about it).
The same with temp.
I propose:
void delete_element (Node* &head, int index)
{
Node* parent_node = head;
Node* node_to_remove;
//...
We don't need temp if we are removing the head. Also, we generally 0 index things, so we should reflect that too. Thus it becomes:
if (index== 0)
{
node_to_remove= head;
head = head->next;
}
Now we get to the main bit. The loop is just there to step through to the parent node of the node to delete, so we can simplify it a little and add checks to make sure we can't 'fall off' the end of the list.
We then have to make sure there is a node to remove, (so another check). We don't need to check for a node beyond as assigning nullptr isn't a problem (I am assuming that an invalid pointer is set to nullptr here):
{
while(--index && parent_node->next){ //pre-decrement means we stop before the one we want (parent)
parent_node = parent_node->next;}
if (parent_node->next){node_to_remove= parent_node->next;}
else {return;} //no point deleting it if it doesnt exist
parent_node->next = node_to_remove->next;//less indirection is always good. Ok if this is nullptr
}
Incidentally, this fixes a probable off by one error. Which is probably your problem (did it crash every time? only when deleting the last element? next to last?
Now we just need to delete it.
Putting it all together:
void delete_element (Node* &head, int index)
{
Node* parent_node = head;
Node* node_to_remove;
if (index== 0)
{
node_to_remove= head;
head = head->next;
}
else
{
while(--index && parent_node->next){ //pre-decrement means we stop before the one we want (parent)
parent_node = parent_node->next;}
if (parent_node->next){node_to_remove= parent_node->next;}
else {return;} //no point deleting it if it doesnt exist
parent_node->next = node_to_remove->next;//less indirection is always good. Ok if this is nullptr
}
delete node_to_remove;
return;
}
And that should work fine. The checks will prevent us dereferencing null pointers which was (probably) what caused you to crash. Can't tell without full code.
i am trying to create a single linked list using for loop. I end up creating an extra node with a zero value.
Below is my code:
node *insert(node *curPtr) {
node *temp = new node() // create a temp node
curPtr = temp;
for ( int i=1; i < 3; i++ ) {
temp->data = i;
temp->next = new node();
temp = temp->next;
}
return curPtr;
}
void printList(node *curPtr) {
while(curPtr) {
std::cout<<curPtr->data<<std::endl;
curPtr = curPtr->next;
}
}
I get the following output:
1
2
0
Whereas i am expecting
1
2
What do i need to change in my code?
Thanks
The problem here is that you are always making
temp->next = new node();
So, in the while loop of the printList function, there is an extra iteration showing a node that have not been assigned yet and -guess that due a compiler assumption or because you are initializing the value of node.data in the constructor of node- you are getting a value equal to 0 for this node. The quick solution is to change the print function as following:
void printList(node *curPtr) {
while (curPtr->next) {
std::cout << curPtr->data << std::endl;
curPtr = curPtr->next;
}
}
I will prefer to make curPtr->next = null until the moment that it will be a real node to insert at the end of the list.