#include <iostream>
using namespace std;
struct Node{
bool flag;
char letter;
Node* left;
Node* right;
};
typedef Node* Nodeptr;
int stop = 0;
void splitString(string sequence, Nodeptr branch){
//cout << sequence << " ";
//cout << sequence.size() << endl;
if(stop == 20) return;
else stop++;
if(sequence.size() == 1){
branch->flag = true;
branch->letter = sequence[0];
}
else{
int half = sequence.size()/2;
Node* left = new Node;
Node* right = new Node;
branch->flag = false;
branch->left = left;
branch->right = right;
splitString(sequence.substr(0, half), left);
splitString(sequence.substr(half), right);
}
return;
}
void print(Nodeptr root){
if(root->flag)
cout << root->letter;
else{
print(root->left);
print(root->right);
}
return;
}
int main() {
std::cout << "Hello World!\n";
Nodeptr tree = new Node;
splitString("Heaven on ", tree);
print(tree);
//the above two lines run fine
Nodeptr tree2 = new Node;
splitString("Heaven on E", tree2); //this code will run fine
//print(tree2); //this code will give me an EXITED, SEGMENTATION FAULT error
}
Considering that the two lines:
splitString("Heaven on ", tree);
print(tree);
run fine, but these do not:
splitString("Heaven on E", tree2);
//print(tree2); //this code will give me an EXITED, SEGMENTATION FAULT error
I come to think that I have reached the maximum recursion depth. I reviewed my code for the building and traversing the binary tree but I cannot find any problems there. What is the reason for the error? Thanks!
For two reason:
you are using a global, which is a very bad practice, and for example in this case you are not resetting it after the first splitString
you are not managing the case where the string has 0 as size, in the right way
This is a possible implementation of splitString which works (without globals):
void splitString(string sequence, Nodeptr branch){
if(sequence.size() == 1){
branch->flag = true;
branch->letter = sequence[0];
}
else if (sequence.size() > 1){
int half = sequence.size()/2;
Node* left = new Node;
Node* right = new Node;
branch->flag = false;
branch->left = left;
branch->right = right;
splitString(sequence.substr(0, half), left);
splitString(sequence.substr(half), right);
}
else {
branch->flag = true;
branch->letter = '\0';
}
}
There is surely a better way to do this, and i'll encourage you to change the data structor in order to makes it happen (for example don't use the flag to mark the leaves of the tree, just check if there is left is been set or is nullptr)
Related
I have written a function to output a linked list in reverse order. Is there a way I can store the head node?
void output_rev_backtracking(Node *x) {
Node *t=x;
if(x==NULL) {
return;
} else {
output_rev_backtracking(x->next);
if(x==t) {
cout << x->data << "\n";
} else {
cout << x->data << " ";
}
}
}
This code is wrong since "x" changes to "x->next" in every step. How should I store "x" in "t"
void recursive_reverse(Node* current, Node* new_head){
if(!current)
return;
Node* next = current->next;
if(!new_head){
new_head = current;
new_head->next = null;
}else{
current->next = new_head;
new_head = current;
}
recursive_reverse(next, new_head);
}
I was trying to reverse a linked list using recursion but when I tried to print out all the elements of the linked list at first it was printing out elements as expected but after printing out the last element it started printing the last and second last element repeatedly. I tried to debug it and I think the problem is that the last element is pointing towards the second last element whether it should be pointing towards NULL. I am not able to figure out what is wrong with my code so please help me out.
example- input 1,2,3,4,5,6
expected output 6,5,4,3,2,1
actual output 6,5,4,3,2,1,2,1,2 ...
#include<iostream>
using namespace std;
class node{
public:
int val;
node *next;
node(int val)
{
this->val = val;
this->next = NULL;
}
node(int val,node *next)
{
this->val= val;
this->next=next;
}
};
void insertAtTail(node *&head,int val){
node *n = new node(val);
if (head==NULL)
{
head = n;
return;
}
node *temp = head;
while (temp->next!=NULL)
{
temp = temp->next;
}
temp->next=n;
}
void display(node *head)
{
node *n = head;
while (n!=NULL)
{
cout << n->val << "->";
n = n->next;
}
cout << "NULL" << endl;
}
node* reverseRecursive(node *&head)
{
if (head == NULL || head->next==NULL)
{
return head;
}
node *nHead = reverseRecursive(head->next);
head->next->next = head;
head->next == NULL;
return nHead; // 1->2->3->4->5->6->NULL
}
int main()
{
node *head = NULL;
insertAtTail(head,1);
insertAtTail(head,2);
insertAtTail(head,3);
insertAtTail(head,4);
insertAtTail(head,5);
insertAtTail(head,6);
display(head);
node *newhead = reverseRecursive(head);
display(newhead);
return 0;
}
There is a bug in function reverseRecursive().
Line head->next == NULL; should be head->next = NULL;
node* reverseRecursive(node *&head)
{
if (head == NULL || head->next==NULL)
{
return head;
}
node *nHead = reverseRecursive(head->next);
head->next->next = head;
head->next == NULL; // <<< should be head->next = NULL;
return nHead; // 1->2->3->4->5->6->NULL
}
Not sure which compiler you were using, but this statement will typically generate a warning.
I'm new to C++. I'm now trying to create a class with back and forth pointer. My code is listed below:
#include<iostream>
using namespace std;
class Node
{
public:
Node(int d, Node*k = NULL, Node*q = NULL) :data(d), back(k), next(q){};
int data;
Node*next; // point to next value on the list
Node*back; // point to back value on the list
};
int main()
{
int n;
Node*p = NULL;
Node*k = NULL; //k is back
while (cin >> n)
{
p = new Node(n,k);
p->back->next = p;
k = p;
}
for (; p; p = p->back)
cout << p->data << "->";
cout << "*\n";
system("pause");
}
However, I always have this error: "Access violation writing location"
I wonder if anybody have a solution ? Thanks
In the first iteration of the loop p->back is NULL. You get the access violation because you dereference it. Write this instead:
while (cin >> n)
{
p = new Node(n,k);
if (p->back != NULL) // p->back == NULL in the first iteration
p->back->next = p;
k = p;
}
I would like to pick two points from pointcloud and return coordinates of the two points. In order to get down to the problem, I have used the PointPickingEvent of PCL, and written a class containing pointcloud, visualizer, and a vector to store selected points. My code:
#include <pcl/point_cloud.h>
#include <pcl/PCLPointCloud2.h>
#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/common/io.h>
#include <pcl/io/ply_io.h>
#include <pcl/io/vtk_lib_io.h>
#include <pcl/visualization/pcl_visualizer.h>
using namespace pcl;
using namespace std;
class pickPoints {
public:
pickPoints::pickPoints () {
viewer.reset (new pcl::visualization::PCLVisualizer ("Viewer", true));
viewer->registerPointPickingCallback (&pickPoints::pickCallback, *this);
}
~pickPoints () {}
void setInputCloud (PointCloud<PointXYZ>::Ptr cloud)
{
cloudTemp = cloud;
}
vector<float> getpoints() {
return p;
}
void simpleViewer ()
{
// Visualizer
viewer->addPointCloud<pcl::PointXYZ>(cloudTemp, "Cloud");
viewer->resetCameraViewpoint ("Cloud");
viewer->spin();
}
protected:
void pickCallback (const pcl::visualization::PointPickingEvent& event, void*)
{
if (event.getPointIndex () == -1)
return;
PointXYZ picked_point1,picked_point2;
event.getPoints(picked_point1.x,picked_point1.y,picked_point1.z,
picked_point2.x,picked_point2.y,picked_point2.z);
p.push_back(picked_point1.x); // store points
p.push_back(picked_point1.y);
p.push_back(picked_point1.z);
p.push_back(picked_point2.x);
p.push_back(picked_point2.y);
p.push_back(picked_point2.z);
//cout<<"first selected point: "<<p[0]<<" "<<p[1]<<" "<<p[2]<<endl;
//cout<<"second selected point: "<<p[3]<<" "<<p[4]<<" "<<p[5]<<endl;
}
private:
// Point cloud data
PointCloud<pcl::PointXYZ>::Ptr cloudTemp;
// The visualizer
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer;
// The picked point
vector<float> p;
};
int main()
{
//LOAD;
PointCloud<PointXYZ>::Ptr cloud (new PointCloud<PointXYZ> ());
pcl::PolygonMesh mesh;
pcl::io::loadPolygonFilePLY("test.ply", mesh);
pcl::fromPCLPointCloud2(mesh.cloud, *cloud);
pickPoints pickViewer;
pickViewer.setInputCloud(cloud); // A pointer to a cloud
pickViewer.simpleViewer();
vector<float> pointSelected;
pointSelected= pickViewer.getpoints();
cout<<pointSelected[0]<<" "<<pointSelected[1]<<" "<<pointSelected[2]<<endl;
cout<<pointSelected[3]<<" "<<pointSelected[4]<<" "<<pointSelected[5]<<endl;
cin.get();
return 0;
}
But when the code was debugged, I got nothing. Also I know that when picking points with the left button, the SHIFT button should be pressed. Thank you in advance for any help!
I found that the getPoints() method does not work as I expected. However, getPoint() worked well. Here is code to print out the selected points and store them is a vector:
std::vector<pcl::PointXYZ> selectedPoints;
void pointPickingEventOccurred(const pcl::visualization::PointPickingEvent& event, void* viewer_void)
{
float x, y, z;
if (event.getPointIndex() == -1)
{
return;
}
event.getPoint(x, y, z);
std::cout << "Point coordinate ( " << x << ", " << y << ", " << z << ")" << std::endl;
selectedPoints.push_back(pcl::PointXYZ(x, y, z));
}
void displayCloud(pcl::PointCloud<pcl::PointXYZI>::Ptr cloud, const std::string& window_name)
{
if (cloud->size() < 1)
{
std::cout << window_name << " display failure. Cloud contains no points\n";
return;
}
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer(window_name));
pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZI> point_cloud_color_handler(cloud, "intensity");
viewer->addPointCloud< pcl::PointXYZI >(cloud, point_cloud_color_handler, "id");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "id");
viewer->registerKeyboardCallback(keyboardEventOccurred, (void*)viewer.get());
viewer->registerPointPickingCallback(pointPickingEventOccurred, (void*)&viewer);
while (!viewer->wasStopped() && !close_window){
viewer->spinOnce(50);
}
close_window = false;
viewer->close();
}
You can also find distances between the points pretty easily once they are selected.
if (selectedPoints.size() > 1)
{
float distance = pcl::euclideanDistance(selectedPoints[0], selectedPoints[1]);
std::cout << "Distance is " << distance << std::endl;
}
The selectedPoints vector can be emptied with a keyboardEvent if you want to start over picking points.
Queue class
#ifndef Queue_H
#define Queue_H
#include "Car.h"
#include <iostream>
#include <string>
using namespace std;
const int Q_MAX_SIZE = 20;
class Queue {
private:
int size; // size of the queue
Car carQueue[Q_MAX_SIZE];
int front, rear;
public:
Queue();
~Queue();
bool isEmpty();
bool isFull();
void enqueue(Car c);
void dequeue(); // just dequeue the last car in the queue
void dequeue(Car c); // if a certain car wants to go out of the queue midway.
// Condition: Car is not in washing. Meaning is not the 1st item in the queue
void dequeue(int index); // same as the previous comment
Car getFront();
void getCarQueue(Queue);
int length();
Car get(int);
};
Queue::Queue() {
size = 0;
front = 0;
rear = Q_MAX_SIZE -1;
}
Queue::~Queue() {
while(!isEmpty()) {
dequeue();
}
}
void Queue::enqueue(Car c) {
if (!isFull()) {
rear = (rear + 1) % Q_MAX_SIZE; // circular array
carQueue[rear] = c;
size++;
} else {
cout << "Queue is currently full.\n";
}
}
void Queue::dequeue() {
}
void Queue::dequeue(int index) {
if(!isEmpty()) {
front = (front + 1) % Q_MAX_SIZE;
if(front != index) {
carQueue[index-1] = carQueue[index];
rear--;
size--;
} else {
cout << "Not allowed to dequeue the first car in the queue.\n";
}
} else {
cout << "There are no cars to dequeue.\n";
}
}
bool Queue::isEmpty() {
return size == 0;
}
bool Queue::isFull() {
return (size == Q_MAX_SIZE);
}
Car Queue::getFront() {
return carQueue[front];
}
int Queue::length() {
return size;
}
Car Queue::get(int index) {
return carQueue[index-1];
}
void Queue::getCarQueue(Queue q) {
for(int i = 0; i< q.length(); i++)
cout << q.get(i) << endl; // Error here
}
#endif
error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'Car' (or there is no acceptable conversion)
I get this error which is kind of odd. so is there anything wrong? Thanks!
cout has no idea how to process a car object; it has never seen a car object and doesn't know how you output a car as text. cout can only process types it knows about, string, char, int, etc. The specific error is because there is version of operator << that takes an ostream and a car.
There are two options:
Creation an overload for operator<< that takes an ostream and a car. That will show cout how to output a car. This isn't usually done becuase there is usually more than one way your would want to display a car.
Write the output statement so that it manually prints out car properties like
cout << c.getMake() << " " << c.getModel()