I'm new to c++ and I have to work with dynamic arrays:| I need to define a few dynamic arrays inside my header file and access them from main. The problem is that when I'm defining the arrays inside the structs, I get segmentation faults and don't know how to fix them.
Below is my header file.
I'm aware that there are lots of problems with my code and I could use your help. I'm really stuck here.
Thanks in advance.
I expect this code to work fine with dynamic arrays just like it does with vectors. But it's not.
`
#pragma once
#include <iostream>
#include <functional>
#include <algorithm>
#define children_link_Size 149
#define row 15
#define col 100
using namespace std;
int itemListIndex = 0;
int freqIdx = 0;
int childIdx = 0;
int linkIdx = 0;
namespace std {
template <typename T> T* begin(std::pair<T*, T*> const& p)
{
return p.first;
}
template <typename T> T* end(std::pair<T*, T*> const& p)
{
return p.second;
}
}
struct Node
{
int itemValue{};
int order{ 0 };
int freq{ 0 };
Node* parent{ nullptr };
Node* children{};
Node* links{};
Node() {
children = new Node[children_link_Size];
links = new Node[children_link_Size];
}
explicit Node(int const& p_value, int p_order = 0) :itemValue(p_value), order(p_order)
{
++freq;
cout << " + " << itemValue << " (" << order << ")" << endl;
}
bool operator ==(Node const& p_node) const
{
return itemValue == p_node.itemValue;
}
~Node() {
delete[] children;
delete[] links;
}
};
/*struct mySet {
Node* OrderedItems;
mySet()
{
OrderedItems = new Node[uniqueSize];
}
void insert(Node item)
{
for (int i = 0; i < uniqueSize; i++)
{
for (int j = 0; j < i; j++)
{
if (item == OrderedItems[j])
{
break;
}
else
{
OrderedItems[i] = item;
}
}
}
}
~mySet()
{
delete[] OrderedItems;
}
};*/
struct ItemSupport
{
explicit ItemSupport(int p_minSup) { ItemSupport::minSup = p_minSup; }
Node* Itemset = new (nothrow) Node[row];
Node* OrderedItems = new (nothrow) Node[row];
ItemSupport& operator<<(int const& p_itemValue)
{
static int order = 0;
auto inode = find_if(Itemset, Itemset + row, [&p_itemValue](Node const& p_node)
{
return p_node.itemValue == p_itemValue;
});
if (inode == Itemset + row)
{
Node node(p_itemValue, order);
Itemset[itemListIndex] = node;
itemListIndex++;
++order;
}
else
{
auto& node = (*inode);
++node.freq;
}
return *this;
}
friend ostream& operator<<(ostream& p_os, ItemSupport const& p_itemSupport)
{
ItemSupport* NoDe = {0};
if (NoDe)
{
NoDe->OrderedItems = p_itemSupport.getFrequentItems();
for (Node node : std::make_pair(NoDe->OrderedItems, NoDe->OrderedItems + row))
{
p_os << node.itemValue << ": support " << node.freq << ", order " << node.order << endl;
}
return p_os;
}
}
Node* getItem(int const& p_itemValue)
{
auto inode = find_if(Itemset, Itemset + row, [&p_itemValue](Node const& p_node)
{
return p_node.itemValue == p_itemValue;
});
if (inode != Itemset + row)
{
Node* node = const_cast<Node*>(&(*inode));
return node;
}
return nullptr;
}
static int getMinSup()
{
return minSup;
}
static int minSup;
private:
Node* getFrequentItems() const
{
int j = 0;
for (int i = 0; i < row; i++)
{
if (Itemset[i].freq >= minSup)
OrderedItems[j++] = Itemset[i];
}
return OrderedItems;
}
Node* getUnfrequentItems() const
{
int j = 0;
for (int i = 0; i < row; i++)
{
if (Itemset[i].freq <= minSup)
OrderedItems[j++] = Itemset[i];
}
return OrderedItems;
}
/*~ItemSupport() {
//delete[] Itemset;
//delete[] OrderedItems;
}*/
};
int ItemSupport::minSup = 0;
struct FP_Tree
{
explicit FP_Tree(ItemSupport& p_itemSupport, const int& p_rootValue = int()) :_headItemSupport(p_itemSupport)
{
_root = new Node(p_rootValue);
}
//void construct(Transaction const& p_itemValues)
void construct(int *p_itemValues)
{
// A. Order items into transaction
ItemSupport* ordered = {0};
for (int const& itemValue : std::make_pair(p_itemValues, p_itemValues + row))
{
Node* pNode = _headItemSupport.getItem(itemValue);
if (pNode && pNode->freq >= ItemSupport::getMinSup())
{
if (ordered)
{
ordered->OrderedItems[freqIdx] = *pNode;
freqIdx++;
}
}
}
// B. Create FP_TREE
Node* actualNode = _root;
bool here = true;
string tab;
if (ordered)
{
for (Node const& node : std::make_pair(ordered->OrderedItems, ordered->OrderedItems + row))
{
tab += "\t-";
auto it = actualNode->children;
if (here)
{
auto it = find_if(actualNode->children,
actualNode->children + children_link_Size,
[&node](Node const& nodeTmp) {
return node == (nodeTmp);
});
here &= it != actualNode->children + children_link_Size;
}
if (here)
{
actualNode = it;
++actualNode->freq;
}
else
{
Node* pNode = new Node(node.itemValue);
actualNode->children[childIdx++] = *pNode;
pNode->parent = actualNode;
Node* pNodeHead = _headItemSupport.getItem(node.itemValue);
pNodeHead->links[linkIdx++] = *pNode;
actualNode = pNode;
delete pNode;
}
//cout << tab << actualNode->_itemValue << "(" << actualNode->_freq << ")" << endl;
}
}
//cout << endl;
}
ItemSupport& headItemSupport() const
{
return _headItemSupport;
}
public:
Node* root() const
{
return _root;
}
private:
ItemSupport& _headItemSupport;
Node* _root;
};
`
I expect this code to work fine with dynamic arrays just like it does with vectors
Since you are using C++, do use std::vector -- it will save you a lot of trouble and there is no reason not to.
Related
I am going to create a single linked list and construct a function (Locate()) that returns the address of the element.But in the end, I didn't see the result of this function. I tried it. This function should be run, but the result is different from what I expected.
use vs2019 on WIndows10,a student:)
#include<iostream>
using namespace std;
struct Node { //Node
int data;
Node* link;
Node(int item, Node* l = NULL)
{
data = item;
link = l;
}
Node(Node* l = NULL)
{
data = 0;
link = l;
}
};
class Link :public Node { //Link
private:
Node* first;
public:
Link(Node* l = NULL)
{
first = l;
}
Link(int d, Node* l = NULL)
{
first = new Node(d);
}
Node* Locate(int i);
};
Node* Link::Locate(int i) //Locate()
{
if (i < 0)
{
cerr << "wrong operation when locating" << endl;
exit(1);
}
int count = 0;
Node* current = first;
while (count < i && current->link != NULL)
{
current = current->link;
count++;
}
return current;
}
int main()
{
Link a;
Node* b = new Node(1);
Node* c = new Node(2);
a.link = b;
b->link = c;
cout << a.data << ' ' << b->data << ' '<<c->data<<endl;
cout << a.Locate(1) << endl;
return 0;
}
Will not output the result of this function 'Locate()' being called
Locate() accesses first->link. At that time, first is a null pointer. Whereupon your program exhibits undefined behavior; in practice, it most likely crashes.
When I re-modify the List constructor, its(Locate()) output is normal and the expected result is obtained.
The modified constructors are as follows:
Link()
{
first = new Node;
}
Link(int d)
{
first = new Node(d);
}
Node* Locate(int i);
Given an infinite stream of characters and a list L of strings, create a function that calls an external API when a word in L is recognized during the processing of the stream.
Example:
L = ["ok","test","one","try","trying"]
stream = a,b,c,o,k,d,e,f,t,r,y,i,n,g.............
The call to external API will happen when 'k' is encountered, again when the 'y' is encountered, and again at 'g'.
My idea:
Create trie out of the list and navigate the nodes as you read from stream in linear time. But there would be a bug if you just do simple trie search.
Assume you have words "abxyz" and "xyw" and your input is "abxyw".In this case you can't recognize "xyw" with trie.
So search should be modified as below:
let's take above use case "abxyw". We start the search and we find we have all the element till 'x'. Moment you get 'x' you have two options:
Check if the current element is equal to the head of trie and if it is equal to head of trie then call recursive search.
Continue till the end of current word. In this case for your given input it will return false but for the recursive search we started in point 1, it will return true.
Below is my modified search but I think it has bugs and can be improved. Any suggestions?
#define SIZE 26
struct tri{
int complete;
struct tri *child[SIZE];
};
void insert(char *c, struct tri **t)
{
struct tri *current = *t;
while(*c != '\0')
{
int i;
int letter = *c - 'a';
if(current->child[letter] == NULL) {
current->child[letter] = malloc(sizeof(*current));
memset(current->child[letter], 0, sizeof(struct tri));
}
current = current->child[letter];
c++;
}
current->complete = 1;
}
struct tri *t;
int flag = 0;
int found(char *c, struct tri *tt)
{
struct tri *current = tt;
if (current == NULL)
return 0;
while(*c != '\0')
{
int i;
int letter = *c - 'a';
/* if this is the first char then recurse from begining*/
if (t->child[letter] != NULL)
flag = found(c+1, t->child[letter]);
if (flag == 1)
return 1;
if(!flag && current->child[letter] == NULL) {
return 0;
}
current = current->child[letter];
c++;
}
return current->complete;
}
int main()
{
int i;
t = malloc(sizeof(*t));
t->complete = 0;
memset(t, 0, sizeof(struct tri));
insert("weathez", &t);
insert("eather", &t);
insert("weather", &t);
(1 ==found("weather", t))?printf("found\n"):printf("not found\n");
return 0;
}
What you want to do is exactly what Aho-Corasick algorithm does.
You can take a look at my Aho-Corasick implementation. It's contest-oriented, so maybe not focused on readability but I think it's quite clear:
typedef vector<int> VI;
struct Node {
int size;
Node *fail, *output;
VI id;
map<char, Node*> next;
};
typedef pair<Node*, Node*> P;
typedef map<char, Node*> MCP;
Node* root;
inline void init() {
root = new Node;
root->size = 0;
root->output = root->fail = NULL;
}
Node* add(string& s, int u, int c = 0, Node* p = root) {
if (p == NULL) {
p = new Node;
p->size = c;
p->fail = p->output = NULL;
}
if (c == s.size()) p->id.push_back(u);
else {
if (not p->next.count(s[c])) p->next[s[c]] = NULL;
p->next[s[c]] = add(s, u, c + 1, p->next[s[c]]);
}
return p;
}
void fill_fail_output() {
queue<pair<char, P> > Q;
for (MCP::iterator it=root->next.begin();
it!=root->next.end();++it)
Q.push(pair<char, P> (it->first, P(root, it->second)));
while (not Q.empty()) {
Node *pare = Q.front().second.first;
Node *fill = Q.front().second.second;
char c = Q.front().first; Q.pop();
while (pare != root && !pare->fail->next.count(c))
pare=pare->fail;
if (pare == root) fill->fail = root;
else fill->fail = pare->fail->next[c];
if (fill->fail->id.size() != 0)
fill->output = fill->fail;
else fill->output = fill->fail->output;
for (MCP::iterator it=fill->next.begin();
it!=fill->next.end();++it)
Q.push(pair<char,P>(it->first,P(fill,it->second)));
}
}
void match(int c, VI& id) {
for (int i = 0; i < id.size(); ++i) {
cout << "Matching of pattern " << id[i];
cout << " ended at " << c << endl;
}
}
void search(string& s) {
int i = 0, j = 0;
Node *p = root, *q;
while (j < s.size()) {
while (p->next.count(s[j])) {
p = p->next[s[j++]];
if (p->id.size() != 0) match(j - 1, p->id);
q = p->output;
while (q != NULL) {
match(j - 1, q->id);
q = q->output;
}
}
if (p != root) {
p = p->fail;
i = j - p->size;
}
else i = ++j;
}
}
void erase(Node* p = root) {
for (MCP::iterator it = p->next.begin();
it != p->next.end(); ++it)
erase(it->second);
delete p;
}
int main() {
init();
int n;
cin >> n;
for (int i = 0; i < n; ++i) {
string s;
cin >> s;
add(s, i);
}
fill_fail_output();
string text;
cin >> text;
search(text);
erase(root);
}
I tried the following code and I get this error.
An unhandled exception of type 'System.NullReferenceException' occurred in Linkedlist.exe Additional information: Object reference not set to an instance of an object.
I think the problem is in insertlast() and when I checked the solutions to similar problems, they talk about instantiating the new node. I my method i.e. Node *q = new Node; wrong?
struct Node {
int data;
Node* next;
};
int is_list_empty(struct Node*head){
int count=0;
Node* p = head;
while (p!= NULL)
{
++count;
p = p->next;
cout<<"go";
}
return count;
}
void insertlast(struct Node *head,int value)
{
Node *q = new Node;
q->data=value;
q->next=NULL;
Node *p=head;
while(p!=NULL)
{
p=p->next;
}
q=p->next;
}
void display(struct Node *head){
Node*p = head;
while(p!=NULL){
cout <<p->data<< " ";
p=p->next;
}
}
int main(){
//Node *head = NULL;
Node *head;
Node *x ;
x = (Node*)malloc(sizeof(Node));
x->data=112;
x->next = head;
head = x;
display(head);
//works fine upto here and 112 is displayed
insertlast(head,34);
insertlast(head,32);
insertlast(head,44);
display(head);
cout<< is_list_empty(head);
system("Pause");
return 0;
}
You should make head null . Next there is mistake in assigning q back to p (It should be p->next=q ) and your while loop should check only up to p->next!=NULL. See the changes i have made.
struct Node {
int data;
Node* next;
};
int is_list_empty(struct Node*head){
int count=0;
Node* p = head;
while (p!= NULL)
{
++count;
p = p->next;
cout<<"go";
}
return count;
}
void insertlast(struct Node *head,int value)
{
Node *q = new Node;
q->data=value;
q->next=NULL;
Node *p=head;
while(p->next!=NULL)
{
p=p->next;
}
p->next=q;
}
void display(struct Node *head){
Node*p = head;
while(p!=NULL){
cout <<p->data<< " ";
p=p->next;
}
}
int main(){
//Node *head = NULL;
Node *head=NULL;
Node *x ;
x = (Node*)malloc(sizeof(Node));
x->data=112;
x->next = head;
head = x;
display(head);
//works fine upto here and 112 is displayed
insertlast(head,34);
insertlast(head,32);
insertlast(head,44);
display(head);
cout<< is_list_empty(head);
system("Pause");
return 0;
}
I am trying to code a c++ program for sorted insert of a linked list. I have given the code below. The problem is when doing my second insert i.e., insert(&head, 45); the head value is becoming 0 inside insert() function. I could not insert my second element and getting errors. Can anyone please help.
#include "stdafx.h"
#include <conio.h>
#include <iostream>
using namespace std;
struct node
{
int data;
node *next;
};
void insert (node** head, int key)
{
if(*head == NULL)
{
cout <<"List is empty, Inserting at first posistion"<<endl;
*head = new node;
(*head)->data = key;
(*head)->data = NULL;
}
else
{
struct node* temp;
temp = new node;
temp = *head;
if(key < temp->data)
{
cout<<"Key is smaller than first element. Inserting at first and moving"<<endl;
struct node* ctemp = new node;
ctemp->data = key;
ctemp->next = (*head);
//delete(ctemp);
return;
}
while(temp->next != NULL)
{
if(key > temp->data)
{
temp = temp->next;
}else
{
cout<<"Inserting the data at middle"<<temp->data<<" here"<<endl;
struct node* temp1 = new node;
temp1->data = key;
temp1->next = temp->next;
temp->next = temp1;
delete(temp1);
return;
}
}
if(key > temp->data)
{
cout<<"Inserting at last"<<endl;
struct node* last = new node;
last->data = key;
last->next = NULL;
temp->next = last;
delete(last);
return;
}
}
}
void print(struct node *head)
{
struct node* temp = head;
cout<<"Element in the list"<<endl;
while(temp != NULL)
{
cout<<temp->data<<"->";
temp = temp->next;
}
delete(temp);
}
int main()
{
struct node* head = NULL;
insert(&head, 21);
insert(&head, 45);
insert(&head, 5);
print(head);
getch();
delete(head);
return 0;
}
Change (*head)->data = NULL; to (*head)->next = NULL; if the list is empty.
The following program goes into a deadlock. Can anyone please tell me why?
#include<cstdlib>
#include<windows.h>
#include<iostream>
using namespace std;
class CircularQueue
{
public:
CircularQueue(int s)
{
size = s;
array = (int*)malloc(sizeof(int) * size);
head = tail = -1;
InitializeCriticalSection(&critical_section);
}
CircularQueue(void)
{
size = default_size;
array = (int*)malloc(sizeof(int) * size);
head = tail = -1;
InitializeCriticalSection(&critical_section);
}
void initialize(int s)
{
EnterCriticalSection(&critical_section);
size = s;
array = (int*)realloc(array, sizeof(int) * size);
head = tail = -1;
LeaveCriticalSection(&critical_section);
}
void enqueue(int n)
{
EnterCriticalSection(&critical_section);
tail = (tail + 1) % size;
array[tail] = n;
LeaveCriticalSection(&critical_section);
}
int dequeue(void)
{
EnterCriticalSection(&critical_section);
head = (head + 1) % size;
return array[head];
LeaveCriticalSection(&critical_section);
}
private:
int *array;
int size;
int head, tail;
CRITICAL_SECTION critical_section;
bool initialized;
static const int default_size = 10;
};
DWORD WINAPI thread1(LPVOID param)
{
CircularQueue* cqueue = (CircularQueue*)param;
cqueue->enqueue(2);
cout << cqueue->dequeue() << endl;
return 0;
}
DWORD WINAPI thread2(LPVOID param)
{
CircularQueue* cqueue = (CircularQueue*)param;
cqueue->enqueue(3);
cout << cqueue->dequeue() << endl;
return 0;
}
int main(void)
{
HANDLE thread1_handle;
HANDLE thread2_handle;
CircularQueue cqueue;
HANDLE array[2];
thread1_handle = CreateThread(NULL, 0, thread1, &cqueue, 0, NULL);
thread2_handle = CreateThread(NULL, 0, thread2, &cqueue, 0, NULL);
array[0] = thread1_handle;
array[1] = thread2_handle;
WaitForMultipleObjects(1, array, TRUE, INFINITE);
CloseHandle(thread1_handle);
CloseHandle(thread2_handle);
printf("end\n");
return 0;
}
In dequeue(), you have a return statement before the LeaveCriticalSection() call. If you had compiler warnings turned up higher, it would probably have told you about this!