I am writing a linked list using a vector to hold (And I know I shouldn't use a vector). I'm trying to implement a function to insert a node a position x and move all elements after x but for some reason it just takes the element originally at x and over writes all remaining elements with this value.
This is the function I am having problem with:
//Insert element at x index
void LinkedList::insertAt(int x, int data) {
Node* tempNode = new Node();
Node* currentNode = vecList[x];
Node* nextNode = vecList[x + 1];
Node* previousNode = vecList[x - 1];
if(x == count) {
push_back(tempNode, data);
return;
}
else {
count++;
for (int i = 0; i < getSize(); i++){
vecList[x + 1]->next = vecList[x]->next; // tranfer the address of 'temp->next' to 'temp'
vecList[x + 1]->data = vecList[x]->data;
if (vecList[x] == NULL){break;}
}
tempNode->data = data;
tempNode->previous = previousNode;
tempNode->next = nextNode;
tempNode->id = x+1;
vecList[x] = tempNode;
vecList[x - 1]->next = tempNode; //Point previous node to this node
}
}//Adds Node but replaces orignal Node
It places the value passed in into position x, I think my problem is with moving the elements after x.
When I call linkedlist.insertAt(2, 50);, it's doing: 10, 20, 50, 30, 30, but expected: 10, 20, 50, 30 ,40.
Definition of Node:
struct Node {
Node * previous;
Node * next;
int id;
int data;
};
The problem is your loop:
for (int i = 0; i < getSize(); i++){
vecList[x + 1]->next = vecList[x]->next; // tranfer the address of 'temp->next' to 'temp'
vecList[x + 1]->data = vecList[x]->data;
if (vecList[x] == NULL){break;}
}
You're iterating over i, but nothing in the loop actually reads i. So you're just doing the same operation getSize() times. I think you meant to assign vecList[i + 1] to veclist[i]. Also the lower bound of the loop shouldn't be 0, it should be x. Which, for further clarity, the name of that variable should probably be pos or something similar.
Also be careful whenever you are referencing vecList[x + 1] or vecList[x - 1]. What if x is 0 or vecList.size() - 1? You will be pointing to an undefined object.
Related
where am I going wrong in this insertion of the linked list problem?
Node *insertInMiddle(Node *head, int x)
{
Node *temp = new Node(x);
int len = 0;
if (head == NULL)
return temp;
Node *curr = head;
while (curr->next != NULL)
{
len++;
curr = curr->next;
}
Node *curr2 = head;
int mid = ((len % 2) == 0) ? (len / 2) : (len + 1) / 2;
// is the problem here?
while (mid-- >= 1)
curr2 = curr2->next;
temp->next = curr2->next;
curr2->next = temp;
return head;
}
The calculation of mid is such that when the list size is even, the insertion happens too far to the right.
You can actually simplify the initialisation of mid to this:
int mid = (len - 1) / 2;
Or:
int mid = len / 2;
The difference between these two will only be be noticed when the list size is odd, like 1->2->3. If you want to insert 50 in the middle, then the first formula will modify the list to 1->50->2->3, while the second one will produce 1->2->50->3. As there is no true middle place, you'll have to choose what best suits you.
It should give you the wrong output because you are using post decrement of Middle element to >=1 while you traversing to the middle of the list.
Just assume if you have a list of 4 elements let's say 1->2->3->4 when you are iterating to come middle you are using while(mid-- >= 1) that actually brings you to middle -1 element instead of the middle.
Therefore you are inserting node after 1 in the example.
you need to use:
while (mid-- > 1)
I didn't see any other issue with your code.
At first line, get inputs n (the numbers of nodes), m (the numbers of edges), start (the start node Number) and get the undirected m edges/
In the end, I want to print out the dfs result. However, when I used Node*, it changes. I don't intend to change.
class Node {
private:
int n;
Node* next = 0;
public:
Node(int _n) {
n = _n;
}
Node() {};
Node* getNext() {
return next;
}
void setNext(Node* ptr) {
next = ptr;
}
};
Below code are the main problem.
Node* arr = new Node[n + 1];// use 1 to n
for (int i = 1; i <= m; i++) {
int num1 = 0, num2 = 0;
cin >> num1 >> num2;
if (!arr[num1].getNext())
arr[num1].setNext(&Node(num2));
else {
Node* tptr = arr[num1].getNext();
while (tptr->getNext()) tptr = tptr->getNext();
tptr->setNext(&Node(num2));
}
}
I tried to save the adjacent Nodes(to Node 'i') in the arr[i].
Sample code is:
4 5 1
1 2
1 3
1 4
The result structure I expected was arr[1] -> 2 -> 3 -> 4, but the real outcome was arr[1]-> 2 -> 4 -> 4.
I don't understand why the value changes.
I'm trying to print a b tree in level order,but it keeps on crashing. Im not sure whats the real reason but i think its crashing because of the pointers. Im trying to use a function i found online that goes through each level and puts it in a queue and prints it, but ive run into this problem.If anyone has another way of doing it please let me know.
// C++ program for B-Tree insertion
#include<iostream>
#include <queue>
using namespace std;
int ComparisonCount = 0;
// A BTree node
class BTreeNode
{
int *keys; // An array of keys
int t; // Minimum degree (defines the range for number of keys)
BTreeNode **C; // An array of child pointers
int n; // Current number of keys
bool leaf; // Is true when node is leaf. Otherwise false
public:
BTreeNode(int _t, bool _leaf); // Constructor
// A utility function to insert a new key in the subtree rooted with
// this node. The assumption is, the node must be non-full when this
// function is called
void insertNonFull(int k);
// A utility function to split the child y of this node. i is index of y in
// child array C[]. The Child y must be full when this function is called
void splitChild(int i, BTreeNode *y);
// A function to traverse all nodes in a subtree rooted with this node
void traverse();
// A function to search a key in subtree rooted with this node.
BTreeNode *search(int k); // returns NULL if k is not present.
// Make BTree friend of this so that we can access private members of this
// class in BTree functions
friend class BTree;
};
// A BTree
class BTree
{
BTreeNode *root; // Pointer to root node
int t; // Minimum degree
public:
// Constructor (Initializes tree as empty)
BTree(int _t)
{
root = NULL; t = _t;
}
// function to traverse the tree
void traverse()
{
if (root != NULL) root->traverse();
}
// function to search a key in this tree
BTreeNode* search(int k)
{
return (root == NULL) ? NULL : root->search(k);
}
// The main function that inserts a new key in this B-Tree
void insert(int k);
};
// Constructor for BTreeNode class
BTreeNode::BTreeNode(int t1, bool leaf1)
{
// Copy the given minimum degree and leaf property
t = t1;
leaf = leaf1;
// Allocate memory for maximum number of possible keys
// and child pointers
keys = new int[2 * t - 1];
C = new BTreeNode *[2 * t];
// Initialize the number of keys as 0
n = 0;
}
// Function to traverse all nodes in a subtree rooted with this node
/*void BTreeNode::traverse()
{
// There are n keys and n+1 children, travers through n keys
// and first n children
int i;
for (i = 0; i < n; i++)
{
// If this is not leaf, then before printing key[i],
// traverse the subtree rooted with child C[i].
if (leaf == false)
{
ComparisonCount++;
C[i]->traverse();
}
cout << " " << keys[i];
}
// Print the subtree rooted with last child
if (leaf == false)
{
ComparisonCount++;
C[i]->traverse();
}
}*/
// Function to search key k in subtree rooted with this node
BTreeNode *BTreeNode::search(int k)
{
// Find the first key greater than or equal to k
int i = 0;
while (i < n && k > keys[i])
i++;
// If the found key is equal to k, return this node
if (keys[i] == k)
{
ComparisonCount++;
return this;
}
// If key is not found here and this is a leaf node
if (leaf == true)
{
ComparisonCount++;
return NULL;
}
// Go to the appropriate child
return C[i]->search(k);
}
// The main function that inserts a new key in this B-Tree
void BTree::insert(int k)
{
// If tree is empty
if (root == NULL)
{
ComparisonCount++;
// Allocate memory for root
root = new BTreeNode(t, true);
root->keys[0] = k; // Insert key
root->n = 1; // Update number of keys in root
}
else // If tree is not empty
{
// If root is full, then tree grows in height
if (root->n == 2 * t - 1)
{
ComparisonCount++;
// Allocate memory for new root
BTreeNode *s = new BTreeNode(t, false);
// Make old root as child of new root
s->C[0] = root;
// Split the old root and move 1 key to the new root
s->splitChild(0, root);
// New root has two children now. Decide which of the
// two children is going to have new key
int i = 0;
if (s->keys[0] < k)
{
ComparisonCount++;
i++;
}s->C[i]->insertNonFull(k);
// Change root
root = s;
}
else // If root is not full, call insertNonFull for root
root->insertNonFull(k);
}
}
// A utility function to insert a new key in this node
// The assumption is, the node must be non-full when this
// function is called
void BTreeNode::insertNonFull(int k)
{
// Initialize index as index of rightmost element
int i = n - 1;
// If this is a leaf node
if (leaf == true)
{
ComparisonCount++;
// The following loop does two things
// a) Finds the location of new key to be inserted
// b) Moves all greater keys to one place ahead
while (i >= 0 && keys[i] > k)
{
keys[i + 1] = keys[i];
i--;
}
// Insert the new key at found location
keys[i + 1] = k;
n = n + 1;
}
else // If this node is not leaf
{
// Find the child which is going to have the new key
while (i >= 0 && keys[i] > k)
i--;
// See if the found child is full
if (C[i + 1]->n == 2 * t - 1)
{
ComparisonCount++;
// If the child is full, then split it
splitChild(i + 1, C[i + 1]);
// After split, the middle key of C[i] goes up and
// C[i] is splitted into two. See which of the two
// is going to have the new key
if (keys[i + 1] < k)
i++;
}
C[i + 1]->insertNonFull(k);
}
}
// A utility function to split the child y of this node
// Note that y must be full when this function is called
void BTreeNode::splitChild(int i, BTreeNode *y)
{
// Create a new node which is going to store (t-1) keys
// of y
BTreeNode *z = new BTreeNode(y->t, y->leaf);
z->n = t - 1;
// Copy the last (t-1) keys of y to z
for (int j = 0; j < t - 1; j++)
z->keys[j] = y->keys[j + t];
// Copy the last t children of y to z
if (y->leaf == false)
{
ComparisonCount++;
for (int j = 0; j < t; j++)
z->C[j] = y->C[j + t];
}
// Reduce the number of keys in y
y->n = t - 1;
// Since this node is going to have a new child,
// create space of new child
for (int j = n; j >= i + 1; j--)
C[j + 1] = C[j];
// Link the new child to this node
C[i + 1] = z;
// A key of y will move to this node. Find location of
// new key and move all greater keys one space ahead
for (int j = n - 1; j >= i; j--)
keys[j + 1] = keys[j];
// Copy the middle key of y to this node
keys[i] = y->keys[t - 1];
// Increment count of keys in this node
n = n + 1;
}
void BTreeNode::traverse()
{
std::queue<BTreeNode*> queue;
queue.push(this);
while (!queue.empty())
{
BTreeNode* current = queue.front();
queue.pop();
int i;
for (i = 0; i < n; i++)
{
if (leaf == false)
queue.push(current->C[i]);
cout << " " << current->keys[i] << endl;
}
if (leaf == false)
queue.push(current->C[i]);
}
}
// Driver program to test above functions
int main()
{
BTree t(4); // A B-Tree with minium degree 4
srand(29324);
for (int i = 0; i<200; i++)
{
int p = rand() % 10000;
t.insert(p);
}
cout << "Traversal of the constucted tree is ";
t.traverse();
int k = 6;
(t.search(k) != NULL) ? cout << "\nPresent" : cout << "\nNot Present";
k = 28;
(t.search(k) != NULL) ? cout << "\nPresent" : cout << "\nNot Present";
cout << "There are " << ComparisonCount << " comparison." << endl;
system("pause");
return 0;
}
Your traversal code uses the field values for this as though they were the values for the current node in the loop body.
You need to stick current-> in front of the member references in the loop body like this (in the lines marked with "//*"):
while (!queue.empty())
{
BTreeNode* current = queue.front();
queue.pop();
int i;
for (i = 0; i < current->n; i++) //*
{
if (current->leaf == false) //*
queue.push(current->C[i]);
cout << " " << current->keys[i] << endl;
}
if (current->leaf == false) //*
queue.push(current->C[i]);
}
This is a strong indicator that all the stuff qualified with current-> in reality wants to live in a function where it is this and thus does not need to be named explicitly.
Your code is better organised and more pleasant to read than most debug requests we get here, but it is still fairly brittle and it contains quite a few smelly bits like if (current->leaf == false) instead of if (not current->is_leaf).
You may want to post it over on Code Review when you have got it into working shape; I'm certain that the experienced coders hanging out there can give you lots of valuable advice on how to improve your code.
In order to ease prototyping and development I would strongly advise the following:
use std::vector<> instead of naked arrays during the prototype phase
invalidate invalid entries during development/prototyping (set keys to -1 and pointers to 0)
use assert() for documenting - and checking - local invariants
write functions that verify the structural invariants exactly and call them before/after every function that modifies the structure
compile your code with /Wall /Wextra and clean it up so that it always compiles without warnings
Also, don't use int indiscriminately; the basic type for things that cannot become negative is unsigned (node degree, current key count etc.).
P.S.: it would be easier to build a conforming B-tree by pinning the order on the number of keys (i.e. number of keys can vary between K and 2*K for some K). Pinning the order on the number of pointers makes things more difficult, and one consequence is that the number of keys for 'order' 2 (where a node is allowed to have between 2 and 4 pointers) can vary between 1 and 3. For most folks dealing with B-trees that will be a rather unexpected sight!
Ok, so I have a regular Node list, with members info and next.
I need to use a function, recursively, to calculate the average, and then compare if each node is bigger than the average or not.
int Acount(NodeType* Node, int sum, int& avg){
if (Node == NULL){//last call
avg = sum / avg;
return 0;
}
else {
return (Acount(Node->next, sum + Node->info, ++avg) + (Node->info > avg ? 1 : 0));
}
}
Which is quite simple. Problem is the value returned is always 0.
The problem appears to be with
(Node->info > avg ? 1 : 0));
I've done the tests and when I do the following:
return (Acount(Node->next, sum + Node->info, ++avg) + Node->info;
or
return (Acount(Node->next, sum + Node->info, ++avg) + avg;
Results meet expectations. As in, I'm getting the sum of the Node->info in the first case, and I'm getting average*number of nodes in the second case.
Point of this, I've proved that the function is working perfectly.
Yet when it comes to
(Node->info > avg ? 1 : 0));
Appears to be problematic, which is quite peculiar. if I place for example:
(Node->info == 5 ? 1 : 0));
And there is only one 5 in the nodes, then the function returns 1. So everything is working as intended, yet I keep getting a 0.
The following are the main functions and additional functions for the Node.
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
struct NodeType{
int info;
NodeType *next;
};
//pre: first node passed is not NULL
int Acount(NodeType* Node, int sum, int& avg){
if (Node == NULL){//last call
avg = sum / avg;
return 0;
}
else {
return (Acount(Node->next, sum + Node->info, ++avg) + (Node->info > avg ? 1 : 0));
}
}
void fill(NodeType*& Node){
NodeType *temp;
Node = new NodeType;
Node->info = 0;
Node->next = NULL;
temp = Node;
for (int i = 1; i < 10; i++){
temp->next = new NodeType;
temp = temp->next;
temp->info = i;
temp->next = NULL;
}
}
void print(NodeType* Node){
NodeType *temp = Node;
while (temp != NULL){
cout << temp->info << " ";
temp = temp->next;
}
cout << endl;
}
void Delete(NodeType* Node){
NodeType *temp;
while (Node != NULL){
temp = Node;
Node = Node->next;
delete temp;
}
}
void main(){
int sum = 0, avg = 0;
NodeType *Node;
fill(Node);
print(Node);
cout << Acount(Node, sum, avg) << endl;
Delete(Node);
}
In C++ there is no concept of left-to-right (or right-to-left) evaluation order of expressions. Operator priorities will control associativity, but in the case of f1() + f2() there is no guarantee that f1() is invoked before f2() (and viceversa). It may depend on the compiler or other.
My suggestion is to split the expression into 2 distinct statements as follows:
int tmp = Acount(Node->next, sum + Node->info, ++avg);
return tmp + (Node->info > avg ? 1 : 0);
I am not sure if your code has defined behaviour. But, this line
return (Acount(Node->next, sum + Node->info, ++avg) + (Node->info > avg ? 1 : 0));
depends on if the left summand or the right summand is calculated first.
If it is the left one, then Acount goes down the recursion an incrementing avg until avg equals the number of elements in the list (here 10 when starting from zero called by the main routine). Note, that avg is passed by reference. Thus, when the recursion goes back up, this term in the right summand
Node->info > avg
will never be true because Node->info is set in the fill routine to values smaller then the number of elements.
I don't think your method will work.
In this statement:
return (Acount(Node->next, sum + Node->info, ++avg) + (Node->info > avg ? 1 : 0))
You don't know when the second term has be evaluated. It's not defined in C++.
Here's the queue using array implementation in Robert Sedgewick's book:
class QUEUE {
private:
int* q;
int N;
int head;
int tail;
public:
QUEUE(int maxN) {
q = new int[maxN + 1];
N = maxN + 1; head = N; tail = 0;
}
int empty() const {
return head % N == tail;
}
void put(int item) {
q[tail++] = item; tail = tail % N;
}
int get() {
head = head % N; return q[head++];
}
};
My concern is about the get() method.
Consider the size to be 10;
According to the code, initially, the index of head = 11 and index of tail = 0.
Now, add an element, say 1. So, 1 is placed in the index position 0 and the tail position is incremented to 1.
Now add another say 5. 5 is at index pos 1 and the tail now is index 2.
Now use the get() function, which does: return q[head++]; which is to return the element at head and then increment the head but BOOOOOM!!!!! The head is index no 11 as we have just seen and it has no value stored in it and this must be a huge error. But, this code is correct as it's Robert Sedgewick and we are the one's mistaken. What's going on guys? :(
If you create a queue with size 10 then head equals 10. In get we use
head = head % N;
head = 10 % 10
head = 0
So head is 0 and then we increment it to 1.
You are missing out the `
head = head % n; // this mean head is now the remainder of the division
// between head and N`
It means head is no longer 10;
head = 11 % 11
which is 0 as the remainder of this division is zero.
Therefore, head = 0;
Then when you return q[head++], you are returning q[0] and then you are setting head to 1.