So I'm making a really rudimentary implementation of a circular list. I haven't made the remove function yet. Whenever I run the cpp, I get a seg fault 11. Any feedback would be much appreciated. Thank you.
#include <iostream>
using namespace std;
struct node{
node* next=NULL;
bool tail= false;
int contents;
};
node* start;//start is a pointer that exists at the start of the list before the first element
class CircList{
node *seek;
public:
CircList (){ //creates a list of one node that points to itself
node *b= new node;
b->contents=0;
b->next = b;
start->next=b;
b->tail=true;
}
bool empty(){
if(start->next==NULL){
return true;
}
return false;
}
int size(CircList a){
if(start->next==NULL){
cout<<"size is 0 \n";
return true;
}
seek=start->next;
for(int i=0; i++;){
if(seek->tail==true){
cout<<"size is "<<i;
}
seek=seek->next;
}
return 0;
}
void insert(int pos, int val){
if(start->next ==NULL){//if inseting when the list is empty
node *b= new node;
b->next = b;
b->tail=true;
return;
}
node *b= new node;
b->contents= val;
seek=start->next;
for(int i=0;i<=pos; i++){
if(seek->tail==true){//if inserting at the end
seek->tail=false;
b->tail=true;
seek->next=b;
b->next=start->next;
}
if(pos==i){//if inserting between two nodes
b->next = seek->next;
seek->next = b;
}
seek=seek->next;
}
}
void remove(int a){
seek=start->next;
for(int i=0;i<=a-1; i++){
if(i<a){
seek=seek->next;
}
if(i==a-1){
}
}
}
void display(){
cout<<start->next->contents; //will also be completed in the near future
seek=start->next;
for(int i=0; ;i++){
if(seek->tail==false){
cout<<seek->contents<<"\n";
}
if(seek->tail==true){
cout<<seek->contents<<"\n";
return;
}
}
}
};
That was the .h file. The following is the cpp. I just plugged in numbers to test. I want to get the program running so that I can test how it behaves.
#include <iostream>
#include "CircList.h"
using namespace std;
int main(){
CircList a;
a.insert (5,5);
a.insert (5,5);
a.insert (1,4);
a.insert (20,65);
a.insert (3,7);
a.size(a);
a.display();
}
I kept treating start as a node instead of a pointer. By making start = Null and replacing all the "start->next"'s with "start", I got it to compile and run. But now it's only infinitely inserting nodes with a value of 0 in the contents.
Edit: I fixed it. By changing that weird for loop in the display function to a while loop, it doesn't do infinite inserts of the node in the constructor, anymore. It seems to work decently enough now.
This here causes a seg fault
start->next=b;
because start is NULL at the start of the program so you are de-referencing a null pointer.
instead set start to the first node in your constructor
start = b;
Your global variable start is an uninitialized pointer, yet you dereference it all over the place.
Related
I am working on a pretty basic binary tree implementation in C++, but I am currently having a problem that deleting a pointer to the root node crashes the program. In Dev-C++ debug mode the error returned is: "Program received signal SIGTRAP, Trace/breakpoint trap", but when I check with "info breakpoints", it says there are no breakpoints or watchpoints. I'm pretty confused about this and have been spending a lot of time checking if I have used and declared all the pointers correctly, any help would greatly be appreciated!
#include <iostream>
#include <vector>
using namespace std;
class Node {
public:
int key;
Node * left_child = NULL;
Node * right_child = NULL;
};
class Tree {
public:
int num_nodes;
vector<Node> nodes;
int read() {
cin >> num_nodes;
nodes.resize(num_nodes);
int input_key, input_left, input_right, root_node = 0;
for (int i = 0; i < num_nodes; i++) {
cin >> input_key >> input_left >> input_right;
if(input_key >= nodes.size()) {
nodes.resize(input_key+1);
}
if(i==0) {
root_node = input_key;
}
nodes[input_key].key = input_key;
if(input_left >= 0) {
nodes[input_key].left_child = &nodes[input_left];
}
if(input_right >= 0) {
nodes[input_key].right_child = &nodes[input_right];
}
}
return root_node;
}
};
int main() {
Tree t;
int root_index = 0;
root_index = t.read();
Node * root_ptr = new Node;
root_ptr = &(t.nodes[root_index]);
delete root_ptr; //when I take this line out, it works
}
Sample Input (no output expected):
3
4 2 5
2 -1 -1
2 -1 -1
Firstly, this line is useless:
Node * root_ptr = new Node;
You immediately reassign root_ptr to something else. So the line does nothing but allocate memory. You then assign root_ptr as follows:
&(t.nodes[root_index]);
The variable t you declared on the stack. You end up getting a pointer to a vector element, an element you never allocated yourself. If you did not allocate it yourself, you cannot delete it. Any allocation by the vector will be handled by the vector, and the vector itself is a stack-allocated, so you cannot delete it.
That is why the delete line crashes.
Additionally, you say it is a simple binary tree implementation, but it is not. You have a vector in there, and you have a strange way of assigning the tree elements, so you've created some kind of hybrid data structure.
#ifndef BINARY_TREE_H
#define BINARY_TREE_H
#include<iostream>
#include<vector>
using namespace std;
class Binary_Tree;
static int levelCount=0;
extern vector<vector<Binary_Tree*>> vec;
extern vector<Binary_Tree*> tempVec;
class Binary_Tree
{
public:
Binary_Tree()
{
childNum=0;
data=0;
level=0;
prev=NULL;
next[0]=NULL;
next[1]=NULL;
};
Binary_Tree(int d)
{
childNum=0;
data=d;
level=0;
prev=NULL;
next[0]=NULL;
next[1]=NULL;
levelCount++;
}
void insert_node(int,int,int);
int get_level();
int get_childCount();
friend int set_childNum(Binary_Tree*);
private:
int childNum;
int data;
int level;
Binary_Tree *prev;
Binary_Tree *next[2];
};
#endif // BINARY_TREE_H
Here is the implementation file
#include<iostream>
#include<cmath>
#include "Binary_Tree.h"
using namespace std;
void Binary_Tree::insert_node(int lev, int d, int sib)
{
if(vec.empty())
{
cout<<"You Have to create Root first";
}
else
{
if(set_childNum(vec[lev][sib-1])==0)
{
cout<<"Child cant be created parent Node already has two childs.";
}
else
{
childNum=set_childNum(vec[lev][sib-1]);
data=d;
level=lev+1;
prev=vec[lev][sib];
next[0]=NULL;
next[1]=NULL;
tempVec.clear();
for(int i=0; i<pow(2,(lev+1)); i++)
{
if(i==childNum-1)
{
tempVec.push_back(this);
}
else
tempVec.push_back(vec[lev][i]);
}
vector<vector<Binary_Tree*>>::iterator itr=vec.begin()+(lev+1);
vec.erase(itr);
vec.insert(itr,tempVec);
}
}
}
int set_childNum(Binary_Tree *lstNdAdr)
{
if(lstNdAdr->get_childCount()==0)
return 1;
else if(lstNdAdr->get_childCount()==1)
return 2;
else
return 0;
}
int Binary_Tree::get_level()
{
return level;
}
int Binary_Tree::get_childCount()
{
if(next[0]==NULL)
{
return 0;
}
else if(next[0]!=NULL && next[1]==NULL)
{
return 1;
}
else
{
return 2;
}
}
MAIN.cpp
#include <iostream>
#include<cmath>
#include"Binary_Tree.h"
using namespace std;
vector<vector<Binary_Tree*>> vec;
vector<Binary_Tree*> tempVec;
int main()
{
Binary_Tree tree;
here:
cout<<"Enter your Choice:1.Create Root Of Tree\n"
<<"2.Insert node\n"<<endl;
int choice;
cin>>choice;
switch(choice)
{
case 1:
{
int d;
cout<<"Enter Data to insert: ";
cin>>d;
Binary_Tree treeDummy(d);
tree=treeDummy;
tempVec.push_back(&tree);
vec.push_back(tempVec);
}
break;
case 2:
{
int lev;
int sibbling;
int d;
cout<<"Enter at which level and data and parent's sibling-no.: ";
cin>>lev;
cin>>d;
cin>>sibbling;
if(sibbling>pow(2,lev))
cout<<"Illegal Sibbling Number."<<endl;
else
tree.insert_node(lev,d,sibbling);
}
break;
}
int x;
cin>>x;
if(x==5)
{
cout<<endl<<endl;
goto here;
}
return 0;
}
in above code i am trying to create a binary tree type structure which can be manipulated and traversed dynamically that is any node can be inserted and can be removed at run time (although its incomplete because i am stuck at a problem). While pushing back the tempVec vector the code produces a segmentation fault and i am also doubtful in passing the object stored in vetcor> vec to the functions in the implementation (I am new to Stl and first time dealing with vector of vectors containing pointer to the class types)
The nested vector's entries are only filled if i is set to 1. But you attempt to access its element [0][0] regardless. You have out of bounds access when i is not 1.
There are numerous problems present in your code, that and combined with the poor style and formatting makes it not so fun to debug.
Binary_Tree treeDummy(d);
tree = treeDummy;
tempVec.push_back(&tree);
I'm not sure what you're trying to do here but the above looks wrong. You are shallow copying treeDummy's data over to tree. You'll lose the link to whatever child node tree points to. Afterwards you're pushing that same tree instance into your temporary vector. That means all the elements in your vector ends up pointing to the local variable tree in main. So even if no segfault occurred you would run into aliasing problems since they all refer to the same tree object and not a separate unique BinaryTree instance.
vector< vector<Binary_Tree*> >::iterator itr=vec.begin()+(lev+1);
vec.erase(itr);
vec.insert(itr,tempVec);
Your BinaryTree::insert_node is using an invalidated iterator after performing erase which is undefined behavior.
childNum = set_childNum(vec[lev][sib-1]);
// ...
prev = vec[lev][sib];
The above can access an out-of-bound index in your vector. eg. You push_back a tempVec with only 1 element in it and then call insert_node with sib = 1.
// ...
if(x == 5)
{
cout<<endl<<endl;
goto here;
}
The use of goto is also completely unnecessary here and should be replaced with a traditional while loop that checks for condition != 5.
The higher level problem in your program, however, is that there's no clear constraints and invariants in its design. What assumptions and preconditions do each of those functions need to work? Why use vectors to hold BinaryTree nodes when the class itself should be dealing with that. You should get the overall design sorted out first, otherwise you'll just play whack-a-mole as other bugs crop up.
This is simple ternary tree structure . I have written code correctly but while running it says after some time:
Sorry ternary.exe has stopped working.
Can you tell me the cause of this error.
#include<iostream>
#include<string>
using namespace std;
struct tnode{
int data[2];
tnode *ptr[3];
};
void swap(int *a,int *b){
int t;
t=*a;
*a=*b;
*b=t;
}
//for initializing tnode variables as null or null character
void newtree(tnode *&T){
T->data[0]='\0';
T->data[1]='\0';
T->ptr[0]=NULL;
T->ptr[1]=NULL;
T->ptr[2]=NULL;
}
void fillto(tnode *&T,int a){
if(T->data[0]=='\0'){
T->data[0]=a;
}
else if(T->data[0]!='\0'&&T->data[1]=='\0'){
T->data[1]=a;
if(T->data[0]>T->data[1])
swap(T->data[0],T->data[1]);
}
else{
if(a<T->data[0]){
if(T->ptr[0]==NULL){
T->ptr[0]=new(tnode);
newtree(T->ptr[0]);
}
fillto(T->ptr[0],a);
}
else if(a>T->data[1]){
if(T->ptr[2]==NULL){
T->ptr[2]=new(tnode);
newtree(T->ptr[2]);
}
fillto(T->ptr[2],a);
}
else{
if(T->ptr[1]==NULL){
newtree(T->ptr[1]);
T->ptr[1]=new(tnode);
}
fillto(T->ptr[1],a);
}
}
}
tnode *datatnode(string s){
int l=0;
tnode *T;
tnode *E;
T=new(tnode);
char c[0];
newtree(T);
E=T;
while(l<=s.length()){
c[0]=s[l];
cout<<atoi(c)<<endl;
fillto(T,atoi(c));
l++;
}
return E;
}
int main(){
string s="5398124";
tnode *T;
T=new(tnode);
T=datatnode(s);
cout<<T->data[0];
return 0;
}
You should remove '=' sign as below
tnode *datatnode(string s){
int l=0;
tnode *T;
tnode *E;
T=new(tnode);
char c;
newtree(T);
E=T;
int a = s.length();
while(l<a){
c=s[l];
cout<<atoi(&c)<<endl;
fillto(T,atoi(&c));
l++;
}
return E;
}
Its difficult to say from your code (as mentally you have to run it in your head). Better to debug it out. Call some debug at key points in your code and try to locate the exact line of code.... this could produce a lot of debug depending how big your data-set is.
At a guess I would say that you probably hit a bad address or somthing like this, that is usually why programs die un-expectedly and immediatly! So I would suggest being very secure on your pointer checking. For example:
void fillto(tnode *&T,int a){
if (T != NULL){
if(T->data[0]=='\0')
{
T->data[0]=a;
}
:
:
}
else
{
printf("Warning: NULL pointer!\n");
}
}
Basically any time you use a pointer that is passed in to a function you should check it is not null. This is generally good code practise and may help you to find your bugs :)
Also int initialisation can just be:
int i = 0;
instead of
int i = '\0';
The fundamental flaw that causes the error is in the 'void fillto(tnode *&T,int a)' function:
...
if(T->ptr[1]==NULL){
newtree(T->ptr[1]);
...
}
As the function newtree does not check if the pointer is null, you end up dereferencing a NULL pointer in newtree
It will work if we use Any Primitive Data Type but not Working for ADT Even though all copy constructor ">>" "<<" "=" operators are overloaded and also copy constructor is written you can see every code below Thanks in advance
void main(){
Array <Item> c;//It will work if we use Any Permitive Data Type but not Working for ADT Even though all copy constructor / >> << operators are overloaded
Item obj(334,"Mango Juice",90,"Drinks",10);
c.insertAtStart(obj);
c.insertAtStart(obj);/////The program Crashes Here!!
c.insertAtStart(obj);
c.PrintArray();
cout<<endl;`
////while Array.h is given below
`
#ifndef H_ARRAY
#define H_ARRAY
#include<iostream>
using namespace std;
template<class T>
class Array
{
private:
T *a;
int size; // total size
int length_used; // used size
public:
Array():a(NULL),size(0),length_used(0){}
void insertAtStart( T val){
if(isEmpty()){
a=new T();
a[0]=val;
length_used++;
size++;
cout<<"Pehli condition"<<endl;
}
else{
if(size>length_used){
shiftRight();
a[0]=val;
length_used++;
cout<<"jab size bara ho length_used"<<endl;
}
else if(size==length_used){
cout<<"jab size or length_used braber ho jao 3rd condiot"<<endl;
resizeByOne();
shiftRight();
a[0]=val;
length_used++;
}
}
}
void insertAtEnd( T val){
if(isEmpty()){
a=new T;
a[0]=val;
length_used++;
size++;
}
else{
if(size>length_used){
a[length_used+1]=val;
length_used++;
}
else if(size==length_used){
resizeByOne();
a[length_used]=val;
length_used++;
}
}
}
void deleteFromStart(){
if(isEmpty()){
cout<<"Container is Empty"<<endl;
}
else{
a[0]=='\0';
shiftLeft();
size--;
length_used--;
}
}
void deleteFromEnd(){
if(isEmpty()){
cout<<"Container is Empty"<<endl;
}
else{
a[length_used]='\0';
length_used--;
size--;
}
}
void PrintArray(){
for(int i=0;i<size;i++)
cout<<a[i]<<endl;
}
////////////////////Helper functions///////////////////////
bool isEmpty(){
if(a=='\0')
return 1;
return 0;
}
void shiftRight(){
int tempIterator=size;
for(int i=tempIterator-1;i>=0;i--)
a[i]=a[i-1];
}
void shiftLeft(){
int tempIterator=length_used;
for(int i=0;i<size;i++)
a[i]=a[i+1];
a[0]=NULL;
}
void resizeByOne(){
T *temp=new T[size+1];
for(int i=0;i<length_used;i++)
temp[i]=a[i];
a=NULL;
delete []a;
a=temp;
size++;
}
};
#endif`
void shiftRight()
{
int tempIterator=size;
for(int i=tempIterator-1;i>=0;i--)
a[i]=a[i-1];
}
Last iteration leads to a[0] = a[-1] which can cause access violation, try i>0 as end condition. Access violation in this case is pretty tricky. If memory at a[-1] is accessible (for instance some data is allocated there) then no exception/crash will occur. Exception occurs in undeterministic way.
BTW
a=NULL;
delete []a;
In resizeByOne() method. It will not cause any exceptions (delete is secured), but for sure will cause memory leak.
I am getting a very strange error in my code. This assignment is for a class I'm taking and essentially we are learning how to implement a hash table. The error i'm getting is when I try and rehash to a larger size. Here's the portion of the code giving me the problem, and I'll explain more fully what the problem is.
if(htable->size>=htable->cap)
{
cout<<htable->cap<<endl;
HashTable tempht=*htable;
delete htable;
htable=new HashTable((tempht.cap * 2) + 1);
for (size_t i=0; i<tempht.cap; i++)
{
Node* n=tempht.table[i];
while (n!=NULL)
{
htable->add(n->item);
n=n->next;
}
}
if (htable->table[0]==NULL)
{
cout<<"HOORAY!"<<endl;
}
}
if (htable->table[0]==NULL)
{
cout<<"HOORAY!"<<endl;
}
else
{
cout<<htable->table[0]->item<<endl;
}
htable is a HashTable variable. In the HashTable class it contains an array Node* (Nodes are just objects I created that contain a string and a pointer to the next item in the chain). This part of the code is simply trying to rehash to a larger table. The issue I'm getting is once I exit the first if statement, my table's first value no longer equals NULL (the test I'm running rehashes a table with nothing in it to a table that still has nothing in it, but has a larger capacity). When I run the code, the first htable->table[0]==NULL passes while the second does not, despite there being no changes other than exiting the if statement (my expected result is that the table[0] should be NULL). My best guess is it's some kind of scoping error, but I honestly can't see where the problem is. Any help would be greatly appreciated.
Edit: Just to clarify, the initial hash table has a capacity of 0 (this is one of the project requirements). So when i try to add an item to the table, this if statement is executed (since the size is 0 and the cap is 0, we have to maintain a load factor of 1). I can confirm that once the table reaches the first and second "Hooray" checks, that htable->cap (which is the total capacity of the array) is 1, which is what it should be. The only thing that is getting messed is bucket 0 (which in this case is the only bucket). For whatever reason, it's null before exiting the if statement but not after.
I'm posting my whole HashTable class, let me know if you find anything.
#pragma once
#include <iostream>
#include <string>
#include <fstream>
#include "Node.h"
using namespace std;
class HashTable
{
public:
Node** table;
int size;
int cap;
HashTable (int c)
{
size=0;
cap=c;
table = new Node*[cap];
if (cap>0)
{
for (size_t i=0; i<cap; ++i)
{
table[i]=NULL;
}
}
}
~HashTable()
{
delete table;
}
size_t hash(string thing)
{
size_t total=0;
int asci;
char c;
size_t index;
for (size_t i=0; i<thing.length(); i++)
{
total=total*31;
c=thing[i];
asci=int(c);
total=asci+total;
}
index=total%cap;
cout<<"index"<<index<<endl;
system("pause");
return index;
}
void add(string thing)
{
size_t index;
index=hash(thing);
cout<<"index "<<index<<endl;
system("pause");
Node* temp=table[index];
if (temp==NULL)
{
cout<<"Here"<<endl;
system("pause");
}
else
{
cout<<"Here2"<<endl;
system("pause");
cout<<"temp"<<temp->item<<endl;
system("pause");
}
Node* n = new Node(thing);
cout<<"n"<<n->item<<endl;
system("pause");
if (temp==NULL)
{
table[index]=n;
}
else
{
while (temp->next!=NULL)
{
temp=temp->next;
}
temp->next=n;
}
size++;
}
Node* find(string search)
{
Node* n= NULL;
size_t index;
if(cap!=0)
{
index=hash(search);
Node* temp=table[index];
while (temp!=NULL)
{
if (temp->item==search)
{
n=temp;
return n;
}
}
}
return n;
}
void remove (string thing)
{
if (find(thing)==NULL)
{
return;
}
else
{
size_t index;
index=hash(thing);
Node* temp=table[index];
if (temp->item==thing)
{
table[index]=temp->next;
delete temp;
}
while (temp->next!=NULL)
{
if (temp->next->item==thing)
{
Node* temp2=temp->next;
temp->next=temp->next->next;
delete temp2;
break;
}
}
}
size--;
}
void print(ofstream &ofile)
{
for (size_t i=0; i<cap; i++)
{
Node* n=table[i];
ofile<<"hash "<<i<<":";
while (n!=NULL)
{
ofile<<" "<<n->item;
n=n->next;
}
}
}
};
Well, this is C++, and I'm more a Java guy, but I'll take a stab at it.
Turns out the problem IS with the
HashTable tempht=*htable;
delete htable;
block after all.
See, the first line there says "copy all of the members from *htable into tempht". So now tempht and htable SHARE their table memory, since table is just a pointer to memory that was allocated at construction, and you just copied the pointer. You wanted it to copy the nodes inside table, but it didn't do that.
So now you have two different HashTable objects with the same pointer value in table. Now, when tempht is freed, the destructor calls free on the table pointer, which effectively frees the table data in both objects htable and tempht.
What you really want to do is write a copy constructor, or do something like:
HashTable *tempht=htable;
htable=new HashTable((tempht->cap * 2) + 1);
for (size_t i=0; i<tempht->cap; i++)
{
Node* n=tempht->table[i];
while (n!=NULL)
{
htable->add(n->item);
n=n->next;
}
}
if (htable->table[0]==NULL)
{
cout<<"HOORAY!"<<endl;
}
delete tempht;
See how all I've really done is change tempht to a pointer, using it to point to the old hashtable while you copy all the nodes from it to the new htable object, then deleting the old Hashtable.