Creating an n array with a linked list of ints - c++

I recently made an 26array and tried to simulate a dictionary.
I can't seem to figure out how to make this. I've tried to work with passing in a linkedlist of ints instead of a string. My current code creates 26 nodes(a-z) and then each of those nodes has 26 nodes(a-z). I would like to implement a way to do this with ints, say (1-26). These int nodes will represent items, and the linkedlist of ints I want to pass in will contain a set of ints that I want represented in the tree similar to a string.
Example: pass in the set {1, 6 , 8}, instead of a string such as "hello"
#include <iostream>
using namespace std;
class N26
{
private:
struct N26Node
{
bool isEnd;
struct N26Node *children[26];
}*head;
public:
N26();
~N26();
void insert(string word);
bool isExists(string word);
void printPath(char searchKey);
};
N26::N26()
{
head = new N26Node();
head->isEnd = false;
}
N26::~N26()
{
}
void N26::insert(string word)
{
N26Node *current = head;
for(int i = 0; i < word.length(); i++)
{
int letter = (int)word[i] - (int)'a';
if(current->children[letter] == NULL)
{
current->children[letter] = new N26Node();
}
current = current->children[letter];
}
current->isEnd = true;
}
/* Pre: A search key
* Post: True is the search key is found in the tree, otherwise false
* Purpose: To determine if a give data exists in the tree or not
******************************************************************************/
bool N26::isExists(string word)
{
N26Node *current = head;
for(int i=0; i<word.length(); i++)
{
if(current->children[((int)word[i]-(int)'a')] == NULL)
{
return false;
}
current = current->children[((int)word[i]-(int)'a')];
}
return current->isEnd;
}

class N26
{
private:
N26Node newNode(void);
N26Node *mRootNode;
...
};
N26Node *newNode(void)
{
N26Node *mRootNode = new N26Node;
mRootNode = NULL;
mRootNode->mData = NULL;
for ( int i = 0; i < 26; i++ )
mRootNode->mAlphabet[i] = NULL;
return mRootNode;
}
Ah! My eyes!
Seriously, you are attempting something much too advanced. Your code is full of bugs and cannot work as intended. Tinkering will not help, you must go back to basics of pointers and linked lists. Study the basics and do not attempt anything like a linked list of linked lists until you understand what is wrong with the code above.
I'll give you some hints: "memory leak", "dangling pointer", "type mismatch", "undefined behavior".

I didnt quite use linked lists, but I managed to get it working using arrays.
/* *** Author: Jamie Roland
* Class: CSI 281
* Institute: Champlain College
* Last Update: October 31, 2012
*
* Description:
* This class is to implement an n26 trie. The
* operations
* available for this impementation are:
*
* 1. insert
* 2. isEmpty
* 3. isExists
* 4. remove
* 5. showInOrder
* 6. showPreOrder
* 7. showPostOrder
*
* Certification of Authenticity:
* I certify that this assignment is entirely my own work.
**********************************************************************/
#include <iostream>
using namespace std;
class N26
{
private:
struct N26Node
{
bool isEnd;
struct N26Node *children[26];
}*head;
public:
N26();
~N26();
void insert(int word[]);
bool isExists(int word[]);
void printPath(char searchKey);
};
N26::N26()
{
head = new N26Node();
head->isEnd = false;
}
N26::~N26()
{
}
void N26::insert(int word[])
{
int size = sizeof word/sizeof(int);
N26Node *current = head;
for(int i = 0; i < size; i++)
{
int letter = word[i] - 1;
if(current->children[letter] == NULL)
{
current->children[letter] = new N26Node();
}
current = current->children[letter];
}
current->isEnd = true;
}
/* Pre: A search key
* Post: True is the search key is found in the tree, otherwise false
* Purpose: To determine if a give data exists in the tree or not
******************************************************************************/
bool N26::isExists(int word[])
{
int size = sizeof word/sizeof(int);
N26Node *current = head;
for(int i=0; i<size; i++)
{
if(current->children[(word[i]-1)] == NULL)
{
return false;
}
current = current->children[(word[i]-1)];
}
return current->isEnd;
}

Related

Hash table implementation in C++

I am trying the following code for Hash table implementation in C++. The program compiles and accepts input and then a popup appears saying " the project has stopped working and windows is checking for a solution to the problem. I feel the program is going in the infinite loop somewhere. Can anyone spot the mistake?? Please help!
#include <iostream>
#include <stdlib.h>
#include <string>
#include <sstream>
using namespace std;
/* Definitions as shown */
typedef struct CellType* Position;
typedef int ElementType;
struct CellType{
ElementType value;
Position next;
};
/* *** Implements a List ADT with necessary functions.
You may make use of these functions (need not use all) to implement your HashTable ADT */
class List{
private:
Position listHead;
int count;
public:
//Initializes the number of nodes in the list
void setCount(int num){
count = num;
}
//Creates an empty list
void makeEmptyList(){
listHead = new CellType;
listHead->next = NULL;
}
//Inserts an element after Position p
int insertList(ElementType data, Position p){
Position temp;
temp = p->next;
p->next = new CellType;
p->next->next = temp;
p->next->value = data;
return ++count;
}
//Returns pointer to the last node
Position end(){
Position p;
p = listHead;
while (p->next != NULL){
p = p->next;
}
return p;
}
//Returns number of elements in the list
int getCount(){
return count;
}
};
class HashTable{
private:
List bucket[10];
int bucketIndex;
int numElemBucket;
Position posInsert;
string collision;
bool reportCol; //Helps to print a NO for no collisions
public:
HashTable(){ //constructor
int i;
for (i=0;i<10;i++){
bucket[i].setCount(0);
}
collision = "";
reportCol = false;
}
int insert(int data){
bucketIndex=data%10;
int col;
if(posInsert->next==NULL)
bucket[bucketIndex].insertList(data,posInsert);
else { while(posInsert->next != NULL){
posInsert=posInsert->next;
}
bucket[bucketIndex].insertList(data,posInsert);
reportCol=true;}
if (reportCol==true) col=1;
else col=0;
numElemBucket++;
return col ;
/*code to insert data into
hash table and report collision*/
}
void listCollision(int pos){
cout<< "("<< pos<< "," << bucketIndex << "," << numElemBucket << ")"; /*codeto generate a properly formatted
string to report multiple collisions*/
}
void printCollision();
};
int main(){
HashTable ht;
int i, data;
for (i=0;i<10;i++){
cin>>data;
int abc= ht.insert(data);
if(abc==1){
ht.listCollision(i);/* code to call insert function of HashTable ADT and if there is a collision, use listCollision to generate the list of collisions*/
}
//Prints the concatenated collision list
ht.printCollision();
}}
void HashTable::printCollision(){
if (reportCol == false)
cout <<"NO";
else
cout<<collision;
}
The output of the program is the point where there is a collision in the hash table, thecorresponding bucket number and the number of elements in that bucket.
After trying dubbuging, I come to know that, while calling a constructor you are not emptying the bucket[bucketIndex].
So your Hash Table constructor should be as follow:
HashTable(){ //constructor
int i;
for (i=0;i<10;i++){
bucket[i].setCount(0);
bucket[i].makeEmptyList(); //here we clear for first use
}
collision = "";
reportCol = false;
}
//Creates an empty list
void makeEmptyList(){
listHead = new CellType;
listHead->next = NULL;
}
what you can do is you can get posInsert using
bucket[bucketIndex].end()
so that posInsert-> is defined
and there is no need to
while(posInsert->next != NULL){
posInsert=posInsert->next;
because end() function is doing just that so use end() function

Why this code failed to run

i want to generate a tree of siblings as under
ABCD
/ | \ \
A B C D
ABCD has four nodes i have taken a array for this *next[]. but this code does not run successfully but it produces the sequence. i have written code in main() which provide characters to the enque function. e.g. str.at(x) where x is variable in for loop.
struct node
{
string info;
struct node *next[];
}*root,*child;
string str, goal;
int dept=0,bnod=0,cl,z=0;
void enqueue(string n);
void enqueue(string n)
{
node *p, *temp;
p=new node[sizeof(str.length())];
p->info=n;
for (int x=0;x<str.length();x++)
p->next[x]=NULL;
if(root==NULL)
{
root=p;
child=p;
}
else
{
cout<<" cl="<<cl<<endl;
if(cl<str.length())
{
child->next[cl]=p;
temp=child->next[cl];
cout<<"chile-info "<<temp->info<<endl;
}
else
cout<<" clif="<<cl<<endl;
}
}
OUTPUT
Enter String: sham
cl=0
chile-info s
cl=1
chile-info h
cl=2
chile-info a
cl=3
chile-info m
RUN FAILED (exit value 1, total time: 2s)
Firstly, where does "RUN FAILED" come from? Is that specific to your compiler?
Secondly, about the line p=new node[sizeof(str.length())];, it probably won't give you what you wanted because you're taking the sizeof of an unsigned integer ( which, depending on your platform is likely to give you 4 regardless of the string length. Which is not what you're after - you want the actual length of the string ).
So - since you're already using std::string, why not use std::vector? Your code would look a lot friendlier :-)
If I take the first couple of lines as your desired output ( sorry, the code you posted is very hard to decipher, and I don't think it compiles either, so I'm ignoring it ;-) )
Would something like this work better for you?
#include <iostream>
#include <vector>
#include <string>
typedef struct node
{
std::string info;
std::vector<struct node*> children;
}Node;
Node * enqueue(std::string str)
{
Node * root;
root = new Node();
root->info = str;
for (int x = 0; x < str.length(); x++)
{
Node * temp = new Node();
temp->info = str[x];
root->children.push_back(temp);
}
return root;
}
int main()
{
Node * myRoot = enqueue("ABCD");
std::cout << myRoot->info << "\n";
for( int i = 0; i < myRoot->children.size(); i++)
{
std::cout << myRoot->children[i]->info << ", ";
}
char c;
std::cin >> c;
return 0;
}
Your code seems not full.
At least the line
p=new node[sizeof(str.length())];
seems wrong.
I guess enqueue should be something similar to the following:
struct node
{
string info;
struct node *next; // [] - is not necessary here
}*root,*child;
string str, goal;
int dept=0,bnod=0,cl,z=0;
void enqueue(string n)
{
node *p, *temp;
p = new node;
p->next = new node[str.length()];
p->info=n;
for (int x=0;x<str.length();x++)
{
p->next[x] = new node;
p->next[x]->next = 0;
p->next[x]->info = str[x];
}
if(root==NULL)
{
root=p;
child=p;
}
}
Please provide more info to give a more correct answer

Trie Implementation in C++

I am trying to implement the trie as shown on the TopCoder page. I am modifying it a bit to store the phone numbers of the users. I am getting segmentation fault. Can some one please point out the error.
#include<iostream>
#include<stdlib.h>
using namespace std;
struct node{
int words;
int prefix;
long phone;
struct node* children[26];
};
struct node* initialize(struct node* root) {
root = new (struct node);
for(int i=0;i<26;i++){
root->children[i] = NULL;
}
root->word = 0;
root->prefix = 0;
return root;
}
int getIndex(char l) {
if(l>='A' && l<='Z'){
return l-'A';
}else if(l>='a' && l<='z'){
return l-'a';
}
}
void add(struct node* root, char * name, int data) {
if(*(name)== '\0') {
root->words = root->words+1;
root->phone = data;
} else {
root->prefix = root->prefix + 1;
char ch = *name;
int index = getIndex(ch);
if(root->children[ch]==NULL) {
struct node* temp = NULL;
root->children[ch] = initialize(temp);
}
add(root->children[ch],name++, data);
}
}
int main(){
struct node* root = NULL;
root = initialize(root);
add(root,(char *)"test",1111111111);
add(root,(char *)"teser",2222222222);
cout<<root->prefix<<endl;
return 0;
}
Added a new function after making suggested changes:
void getPhone(struct node* root, char* name){
while(*(name) != '\0' || root!=NULL) {
char ch = *name;
int index = getIndex(ch);
root = root->children[ch];
++name;
}
if(*(name) == '\0'){
cout<<root->phone<<endl;
}
}
Change this:
add(root->children[ch], name++, data);
// ---------------------^^^^^^
To this:
add(root->children[ch], ++name, data);
// ---------------------^^^^^^
The remainder of the issues in this code I leave to you, but that is the cause of your run up call-stack.
EDIT OP ask for further analysis, and while I normally don't do so, this was a fairly simple application on which to expand.
This is done in several places:
int index = getIndex(ch);
root = root->children[ch];
... etc. continue using ch instead of index
It begs the question: "Why did we just ask for an index that we promptly ignore and use the char anyway?" This is done in add() and getPhone(). You should use index after computing it for all peeks inside children[] arrays.
Also, the initialize() function needs to be either revamped or outright thrown out in favor of a constructor-based solution, where that code truly belongs. Finally, if this trie is supposed to be tracking usage counts of words generated and prefixes each level is participating in, I'm not clear why you need both words and prefix counters, but in either case to update the counters your recursive decent in add() should bump them up on the back-recurse.

A Star Unpredictable Errors

My feeble attempt at an A* Algorithm is generating unpredictable errors.
My FindAdjacent() function is clearly a mess, and it actually doesn't work when I step through it. This is my first time trying a path finding algorithm, so this is all new to me.
When the application actually manages to find the goal nodes and path (or so I think), it can never set the path (called from within main by pressing enter). I do not know why it is unable to do this from looking at the SetPath() function.
Any help would be hugely appreciated, here's my code:
NODE CLASS
enum
{
NODE_TYPE_NONE = 0,
NODE_TYPE_NORMAL,
NODE_TYPE_SOLID,
NODE_TYPE_PATH,
NODE_TYPE_GOAL
};
class Node
{
public:
Node () : mTypeID(0), mNodeCost(0), mX(0), mY(0), mParent(0){};
public:
int mTypeID;
int mNodeCost;
int mX;
int mY;
Node* mParent;
};
PATH FINDING
/**
* finds the path between star and goal
*/
void AStarImpl::FindPath()
{
cout << "Finding Path." << endl;
GetGoals();
while (!mGoalFound)
GetF();
}
/**
* modifies linked list to find adjacent, walkable nodes
*/
void AStarImpl::FindAdjacent(Node* pNode)
{
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
if (i != 0 && j != 0)
if (Map::GetInstance()->mMap[pNode->mX+i][pNode->mY+j].mTypeID != NODE_TYPE_SOLID)
{
for (vector<Node*>::iterator iter = mClosedList.begin(); iter != mClosedList.end(); iter++)
{
if ((*iter)->mX != Map::GetInstance()->mMap[pNode->mX + i][pNode->mY + j].mX && (*iter)->mY != Map::GetInstance()->mMap[pNode->mX + i][pNode->mY + j].mY)
{
Map::GetInstance()->mMap[pNode->mX+i][pNode->mY+j].mParent = pNode;
mOpenList.push_back(&Map::GetInstance()->mMap[pNode->mX+i][pNode->mY+j]);
}
}
}
}
mClosedList.push_back(pNode);
}
/**
* colour the found path
*/
void AStarImpl::SetPath()
{
vector<Node*>::iterator tParent;
mGoalNode->mTypeID = NODE_TYPE_PATH;
Node *tNode = mGoalNode;
while (tNode->mParent)
{
tNode->mTypeID = NODE_TYPE_PATH;
tNode = tNode->mParent;
}
}
/**
* returns a random node
*/
Node* AStarImpl::GetRandomNode()
{
int tX = IO::GetInstance()->GetRand(0, MAP_WIDTH - 1);
int tY = IO::GetInstance()->GetRand(0, MAP_HEIGHT - 1);
Node* tNode = &Map::GetInstance()->mMap[tX][tY];
return tNode;
}
/**
* gets the starting and goal nodes, then checks te starting nodes adjacent nodes
*/
void AStarImpl::GetGoals()
{
// get the two nodes
mStartNode = GetRandomNode();
mGoalNode = GetRandomNode();
mStartNode->mTypeID = NODE_TYPE_GOAL;
mGoalNode->mTypeID = NODE_TYPE_GOAL;
// insert start node into the open list
mOpenList.push_back(mStartNode);
// find the starting nodes adjacent ndoes
FindAdjacent(*mOpenList.begin());
// remove starting node from open list
mOpenList.erase(mOpenList.begin());
}
/**
* finds the best f
*/
void AStarImpl::GetF()
{
int tF = 0;
int tBestF = 1000;
vector<Node*>::const_iterator tIter;
vector<Node*>::const_iterator tBestNode;
for (tIter = mOpenList.begin(); tIter != mOpenList.end(); ++tIter)
{
tF = GetH(*tIter);
tF += (*tIter)->mNodeCost;
if (tF < tBestF)
{
tBestF = tF;
tBestNode = tIter;
}
}
if ((*tBestNode) != mGoalNode)
{
Node tNode = **tBestNode;
mOpenList.erase(tBestNode);
FindAdjacent(&tNode);
}
else
{
mClosedList.push_back(mGoalNode);
mGoalFound = true;
}
}
/**
* returns the heuristic from the given node to goal
*/
int AStarImpl::GetH(Node *pNode)
{
int H = (int) fabs((float)pNode->mX - mGoalNode->mX);
H += (int) fabs((float)pNode->mY - mGoalNode->mY);
H *= 10;
return H;
}
A few suggestions:
ADJACENCY TEST
The test in FindAdjacent will only find diagonal neighbours at the moment
if (i != 0 && j != 0)
If you also want to find left/right/up/down neighbours you would want to use
if (i != 0 || j != 0)
ADJACENCY LOOP
I think your code looks suspicious in FindAdjacent at the line
for (vector<Node*>::iterator iter = mClosedList.begin(); iter != mClosedList.end(); iter++)
I don't really understand the intention here. I would have expected mClosedList to start empty, so this loop will never execute, and so nothing will ever get added to mOpenList.
My expectation at this part of the algorithm would be for you to test for each neighbour whether it should be added to the open list.
OPENLIST CHECK
If you look at the A* algorithm on wikipedia you will see that you are also missing the section starting
if neighbor not in openset or tentative_g_score < g_score[neighbor]
in which you should also check in FindAdjacent whether your new node is already in the OpenSet before adding it, and if it is then only add it if the score is better.

Exponential tree implementation

I was trying to implement exponential tree from documentation, but here is one place in the code which is not clear for me how to implement it:
#include<iostream>
using namespace std;
struct node
{
int level;
int count;
node **child;
int data[];
};
int binary_search(node *ptr,int element)
{
if(element>ptr->data[ptr->count-1]) return ptr->count;
int start=0;
int end=ptr->count-1;
int mid=start+(end-start)/2;
while(start<end)
{
if(element>ptr->data[mid]) { start=mid+1;}
else
{
end=mid;
}
mid=start+(end-start)/2;
}
return mid;
}
void insert(node *root,int element)
{
node *ptr=root,*parent=NULL;
int i=0;
while(ptr!=NULL)
{
int level=ptr->level,count=ptr->count;
i=binary_search(ptr,element);
if(count<level){
for(int j=count;j<=i-1;j--)
ptr->data[j]=ptr->data[j-1];
}
ptr->data[i]=element;
ptr->count=count+1;
return ;
}
parent=ptr,ptr=ptr->child[i];
//Create a new Exponential Node at ith child of parent and
//insert element in that
return ;
}
int main()
{
return 0;
}
Here is a link for the paper I'm referring to:
http://www.ijcaonline.org/volume24/number3/pxc3873876.pdf
This place is in comment, how can I create a new exponential node at level i? Like this?
parent->child[i]=new node;
insert(parent,element);
The presence of the empty array at the end of the structure indicates this is C style code rather than C++ (it's a C Hack for flexible arrays). I'll continue with C style code as idiomatic C++ code would prefer use of standard containers for the child and data members.
Some notes and comments on the following code:
There were a number of issues with the pseudo-code in the linked paper to a point where it is better to ignore it and develop the code from scratch. The indentation levels are unclear where loops end, all the loop indexes are not correct, the check for finding an insertion point is incorrect, etc....
I didn't include any code for deleting the allocated memory so the code will leak as is.
Zero-sized arrays may not be supported by all compilers (I believe it is a C99 feature). For example VS2010 gives me warning C4200 saying it will not generate the default copy/assignment methods.
I added the createNode() function which gives the answer to your original question of how to allocate a node at a given level.
A very basic test was added and appears to work but more thorough tests are needed before I would be comfortable with the code.
Besides the incorrect pseudo-code the paper has a number of other errors or at least questionable content. For example, concerning Figure 2 it says "which clearly depicts that the slope of graph is linear" where as the graph is clearly not linear. Even if the author meant "approaching linear" it is at least stretching the truth. I would also be interested in the set of integers they used for testing which doesn't appear to be mentioned at all. I assumed they used a random set but I would like to see at least several sets of random numbers used as well as several predefined sets such as an already sorted or inversely sorted set.
.
int binary_search(node *ptr, int element)
{
if (ptr->count == 0) return 0;
if (element > ptr->data[ptr->count-1]) return ptr->count;
int start = 0;
int end = ptr->count - 1;
int mid = start + (end - start)/2;
while (start < end)
{
if (element > ptr->data[mid])
start = mid + 1;
else
end = mid;
mid = start + (end - start)/2;
}
return mid;
}
node* createNode (const int level)
{
if (level <= 0) return NULL;
/* Allocate node with 2**(level-1) integers */
node* pNewNode = (node *) malloc(sizeof(node) + sizeof(int)*(1 << (level - 1)));
memset(pNewNode->data, 0, sizeof(int) * (1 << (level - 1 )));
/* Allocate 2**level child node pointers */
pNewNode->child = (node **) malloc(sizeof(node *)* (1 << level));
memset(pNewNode->child, 0, sizeof(int) * (1 << level));
pNewNode->count = 0;
pNewNode->level = level;
return pNewNode;
}
void insert(node *root, int element)
{
node *ptr = root;
node *parent = NULL;
int i = 0;
while (ptr != NULL)
{
int level = ptr->level;
int count = ptr->count;
i = binary_search(ptr, element);
if (count < (1 << (level-1)))
{
for(int j = count; j >= i+1; --j)
ptr->data[j] = ptr->data[j-1];
ptr->data[i] = element;
++ptr->count;
return;
}
parent = ptr;
ptr = ptr->child[i];
}
parent->child[i] = createNode(parent->level + 1);
insert(parent->child[i], element);
}
void InOrderTrace(node *root)
{
if (root == NULL) return;
for (int i = 0; i < root->count; ++i)
{
if (root->child[i]) InOrderTrace(root->child[i]);
printf ("%d\n", root->data[i]);
}
if (root->child[root->count]) InOrderTrace(root->child[root->count]);
}
void testdata (void)
{
node* pRoot = createNode(1);
for (int i = 0; i < 10000; ++i)
{
insert(pRoot, rand());
}
InOrderTrace(pRoot);
}