A little trouble with creating a single linked list in C++ - visual-c++

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);

Related

define dynamic array inside a struct without causing a segmentation fault

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.

Find the word in the stream?

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 get "unhandled exception of type 'System.NullReferenceException' occurred" how to solve it?

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;
}

Overloading "*" Operator for custom SmartPointer

I am trying to directly access integer from a pointer class, by overloading * operator, but it seems VC++ 10 is not allowing it. Kindly help:
#include "stdafx.h"
#include <iostream>
#include <conio.h>
using namespace std;
int MAX7 = 10;
struct node{
int value;
node *next;
};
struct node *head = NULL;
struct node *current = NULL;
int count = 0;
class SmartPointer{
public:
SmartPointer(){
}
int push(int i){
if(count == MAX7) return 0;
if(head == NULL){
head = new node();
current = head;
head -> next = NULL;
head -> value = i;
count = 1;
}
else{
struct node *ptr = head;
while(ptr->next != NULL) ptr = ptr->next;
ptr->next = new node;
ptr = ptr->next;
ptr->next = NULL;
ptr->value = i;
count++;
}
return 1;
}
void Display(){
node *ptr = head;
while(ptr != NULL){
cout << ptr->value << "(" << ptr << ")";
if( ptr == current )
cout << "*";
cout << ", ";
ptr = ptr->next;
}
}
int operator *(){
if(current == NULL) return -1;
struct node *ptr = current;
return ptr->value;
}
};
int main(){
SmartPointer *sp;
sp = new SmartPointer();
sp->push(99);
for(int i=100; i<120; i++){
if(sp->push(i))
cout << "\nPushing ("<<i<<"): Successful!";
else
cout << "\nPushing ("<<i<<"): Failed!";
}
cout << "\n";
sp->Display();
int i = *sp;
getch();
return 0;
}
Error#
1>test7.cpp(71): error C2440: 'initializing' : cannot convert from 'SmartPointer' to 'int'
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
sp is not a smart pointer - it's a plain old dumb pointer to SmartPointer class. *sp uses built-in dereference operator, producing an lvalue of SmartPointer type. It does not call SmartPointer::operator*() - for that, you need to write **sp (two stars).
It's not at all clear why you want to allocate SmartPointer instance on the heap. That's an unusual thing to want to do (also too, you leak it). I'm pretty sure you would be better off with
SmartPointer sp;
sp.push(99);
and so on.
short answer:
int i = **sp;
You should not allocate objects with new. Your code looks like java. In C++, you must delete everything you allocate with new. In C++ you can write:
SmartPointer sp;
sp.push(99);
int i = *sp;

Acces violation error with queue and linked list c++

I have an assignment and it's to build a queue linked list.
Our professor gave us the skeleton and told us to use his main.
I wrote my functions and everything compiled right but when I ran it, I got this error.
Don't know what to do from here.
Source Code:
#include<iostream>
using namespace std;
template<class ItemType>
struct NodeType
{
ItemType info;
NodeType* next;
};
template<class ItemType>
class Queue
{
private:
int size;
NodeType<ItemType>* front; // It points to the front of a singly-linked list
NodeType<ItemType>* rear; // It points to the end of a singly-linked list
public:
Queue(); // default constructor: Queue is created and empty
Queue(const Queue<ItemType> &x); // copy constructor: implicitly called
// for a deep copy
void MakeEmpty(); // Queue is made empty; you should deallocate all
// the nodes of the linked list
bool IsEmpty( ); // test if the queue is empty
bool IsFull( ); // test if the queue is full; assume MAXITEM=5
int length( ); // return the number of elements in the queue
void Print( ); // print the value of all elements in the queue in the sequence
// from the front to rear
void Enqueue(ItemType x); // insert x to the rear of the queue
// Precondition: the queue is not full
void Dequeue(ItemType &x); // delete the element from the front of the queue
// Precondition: the queue is not empty
~Queue(); // Destructor: memory for the dynamic array needs to be deallocated
};
template<class ItemType>
Queue<ItemType>::Queue()
{
size = 0;
front = NULL;
rear = NULL;
}
template<class ItemType>
Queue<ItemType>::Queue(const Queue<ItemType> &x)
{
NodeType<ItemType>* ptr1 ;
NodeType<ItemType>* ptr2 ;
if ( x.front == NULL )
{
front = NULL ;
}
else // allocate memory for first node
{
front = new NodeType<ItemType> ;
front->info = x.front->info ;
ptr1 = x.front->next ;
ptr2 = front ;
while ( ptr1 != NULL ) // deep copy other nodes
{
ptr2->next = new NodeType<ItemType> ;
ptr2 = ptr2->next ;
ptr2->info = ptr1->info ;
ptr1 = ptr1->next ;
}
ptr2->next = NULL;
rear = ptr2;
}
}
template<class ItemType>
void Queue<ItemType>::MakeEmpty()
{
NodeType<ItemType>* tempPtr;
while(front != NULL)
{
tempPtr = front;
front = front->next;
delete tempPtr;
}
rear=NULL;
}
template<class ItemType>
bool Queue<ItemType>::IsEmpty()
{
return (size == 0);
}
template<class ItemType>
bool Queue<ItemType>::IsFull()
{
return (size >= 5);
}
template<class ItemType>
int Queue<ItemType>::length()
{
return size;
}
template<class ItemType>
void Queue<ItemType>::Enqueue(ItemType x)
{
NodeType<ItemType>* newNode;
newNode = new NodeType<ItemType>;
newNode->info = x;
newNode->next = NULL;
if(rear == NULL)
{
front = newNode;
}
else
{
rear->next = newNode;
rear = newNode;
}
size++;
}
template<class ItemType>
void Queue<ItemType>::Dequeue(ItemType &x)
{
NodeType<ItemType>* tempPtr;
if(!IsEmpty())
{
tempPtr = front;
x = front->info;
front = front->next;
if(front == NULL)
{
rear = NULL;
}
delete tempPtr;
}
size--;
}
template<class ItemType>
void Queue<ItemType>::Print()
{
NodeType<ItemType> *temp;
temp = rear;
while(temp != NULL)
{
cout<<temp->info<<endl;
temp = temp->next;
}
}
template<class ItemType>
Queue<ItemType>::~Queue()
{
MakeEmpty();
}
int main()
{
Queue<int>IntQueue;
int x;
IntQueue.MakeEmpty();
IntQueue.Dequeue(x);
IntQueue.Enqueue(10);
IntQueue.Enqueue(20);
IntQueue.Enqueue(30);
IntQueue.Enqueue(40);
cout << "int length 3 = " << IntQueue.length() << endl;
IntQueue.Dequeue(x);
cout << "int length 4 = " << IntQueue.length() << endl;
cout << "The int queue contains: " << endl;
IntQueue.Print();
if(IntQueue.IsFull() == false)
cout << "The int queue is not full !" << endl;
else
cout << "The int queue is full !" << endl;
Queue<float>FloatQueue;
float y;
FloatQueue.MakeEmpty();
FloatQueue.Dequeue(y);
FloatQueue.Enqueue(7.1);
cout << "float length 3 = " << FloatQueue.length() << endl;
FloatQueue.Enqueue(2.3);
cout << "float length 4 = " << FloatQueue.length() << endl;
FloatQueue.Enqueue(3.1);
FloatQueue.Dequeue(y);
cout << "The float queue contains: " << endl;
FloatQueue.Print();
Queue<float> FloatQueue2 = FloatQueue;
cout << "The float queue 2 contains: " << endl;
FloatQueue2.Print();
FloatQueue.MakeEmpty();
cout << "The float queue 3 contains: " << endl;
FloatQueue2.Print();
system("pause");
return 0;
}
The problem I'm having is obviously with the print function.
Any help is appreciated.
Inside your copy constructor, you aren't setting rear to anything when x.front == NULL. This sets temp to an invalid value inside Print, causing you both to loop when you shouldn't and dereference an invalid pointer.

Resources