Puzzled by Sort comparison method in C++ - c++

I tried two comparison methods, and did not get expected result.
The first comparison method is inside of a customized class MyTreeNode as operator<; The second one is a new comparison class compare with an override method operator()(MyTreeNode*) .
The code is shown below. Both outputs are:
5 6 1
while the expected order should be 1 5 6.
The rule for the ordering is: If two nodes have the same x, then the node with a larger y value comes first. If nodes have equal both x and y, then the node with less treeNode->val comes first.
So, can anyone help explain it for me ? Thanks
#include <vector>
#include <cstddef>
#include <algorithm>
#include <iostream>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x) {}
};
class MyTreeNode{
public:
TreeNode* treeNode;
int x;
int y;
public:
MyTreeNode(TreeNode* node, int _x, int _y): treeNode(node), x(_x), y(_y){
}
//Solution 1.
bool operator<(MyTreeNode& node){
if(x< node.x){
return true;
}
if(x == node.x && y > node.y){
return true;
}
if(x == node.x && y == node.y
&&treeNode->val<node.treeNode->val){
return true;
}
return false;
}
};
//Solution 2
class compare{
public:
bool operator()(MyTreeNode* node1, MyTreeNode* node2){
if(node1->x < node2->x){
return true;
}
if(node1->x == node2->x && node2->y > node1->y){
return true;
}
if(node1->x == node2->x && node2->y == node1->y
&&node1->treeNode->val<node2->treeNode->val){
return true;
}
return false;
}
};
int main(int argc, char* argv[]){
//Solution so;
vector<MyTreeNode*> trees;
trees.push_back(new MyTreeNode(new TreeNode(5), 0, -2)); //A
trees.push_back(new MyTreeNode(new TreeNode(6), 0, -2)); //B
trees.push_back(new MyTreeNode(new TreeNode(1), 0, 0)); //C
//Solution 1
sort (trees.begin(), trees.end());
//Solution 2
//sort (trees.begin(), trees.end(), compare()); // print 5 6 1
// for(int i=0; i<res.size(); i++){
for_each(trees.begin(), trees.end(), [](const MyTreeNode* ele){cout<< " "<< ele->treeNode->val ;});
//}
}
```

1. If you want to reverse the order so that
the node with a larger y value comes first,
you should reverse the order in the comparator. Namely, instead of
node2->y > node1->y (which is equivalent to node1->y < node2->y) you should write node2->y < node1->y.
2. Note that the line sort(trees.begin(), trees.end());
will sort elements by their pointer values*, not by element values. The operator MyTreeNode::operator< won't be used - comparison between MyTreeNode* values won't be magically translated into comparison between dereferenced MyTreeNode values. That's not what you want. Use a custom comparator, as in your solution 2.
If you define MyTreeNode::operator<, then you can use a simple lambda as a comparator:
std::sort(trees.begin(), trees.end(), [](auto n1, auto n2) { return *n1 < *n2; });
* std::sort uses operator< to compare elements. The < comparison between two unrelated pointers (which do not point to elements of the same array) is undefined behaviour. std::less should be used as a custom comparator to avoid UB even if you want to sort pointers by their values (addresses).

Related

C Creating a binary tree based on a sequence

I need help adjusting the createTree function.
Which accepts a string and after that character by character traverses it, creating a binary tree based on it
If it encounters the character 0, it recursively creates two sub-branches.
If it encounters another character, it saves it in the leaf node.
For the string in the example, I need to make a tree as in the picture, but the function does not work properly for me. Thank you in advance for your advice.
int x = 0;
Node* createTree(string str, int si, int ei)
{
if (si > ei)
return NULL;
Node *root = new Node((str[si] - '0'));
if(str[si] != '0')
{
x++;
root->m_Data = (str[si] - '0');
return root;
}
if(str[si]=='0')
{
x++;
root->m_Left = createTree(str,x,ei);
root->m_Right = createTree(str,x,ei);
}
return root;
}
int main ()
{
string str = "050067089";
Node *node = createTree(str,0,str.length());
printPreorder(node);
return 0;
}
The problem can quite easily be broken down into small steps (what you partly did in your question).
Start iterating at the first character
Create the root node
If the current character is non-zero, set the value of this node to this character
If current character is a zero, set this node to zero, create a left and a right node and get back to step 3 for every one of them. (That's the recursive part.)
Below is my implementation of this algorithm.
First, a little bit of setting up:
#include <iostream>
#include <string>
#include <memory>
struct Node;
// Iterator to a constant character, NOT a constant iterator
using StrConstIt = std::string::const_iterator;
using UniqueNode = std::unique_ptr<Node>;
struct Node
{
int value;
UniqueNode p_left;
UniqueNode p_right;
Node(int value)
: value(value) {}
Node(int value, UniqueNode p_left, UniqueNode p_right)
: value(value), p_left(std::move(p_left)), p_right(std::move(p_right)) {}
};
As you can see, I'm using std::unique_ptr for managing memory. This way, you don't have to worry about manually deallocating memory. Using smart pointers is often considered the more "modern" approach, and they should virtually always be preferred over raw pointers.
UniqueNode p_createNodeAndUpdateIterator(StrConstIt& it, StrConstIt stringEnd)
{
if (it >= stringEnd)
return nullptr;
UniqueNode node;
if (*it == '0')
// Create node with appropriate value
// Create branches and increment iterator
node = std::make_unique<Node>(
0,
p_createNodeAndUpdateIterator(++it, stringEnd),
p_createNodeAndUpdateIterator(it, stringEnd)
);
else
{
// Create leaf node with appropriate value
node = std::make_unique<Node>(*it - '0');
// Increment iterator
++it;
}
return node;
}
UniqueNode p_createTree(StrConstIt begin, StrConstIt end)
{
return p_createNodeAndUpdateIterator(begin, end);
}
The first function takes a reference to the iterator to the next character it should process. That is because you can't know how much characters a branch will have in its leaf nodes beforehand. Therefore, as the function's name suggests, it will update the iterator with the processing of each character.
I'm using iterators instead of a string and indices. They are clearer and easier to work with in my opinion — changing it back should be fairly easy anyway.
The second function is basically syntactic sugar: it is just there so that you don't have to pass an lvalue as the first argument.
You can then just call p_createTree with:
int main()
{
std::string str = "050067089";
UniqueNode p_root = p_createTree(str.begin(), str.end());
return 0;
}
I also wrote a function to print out the tree's nodes for debugging:
void printTree(const UniqueNode& p_root, int indentation = 0)
{
// Print the value of the node
for (int i(0); i < indentation; ++i)
std::cout << "| ";
std::cout << p_root->value << '\n';
// Do nothing more in case of a leaf node
if (!p_root->p_left.get() && !p_root->p_right.get())
;
// Otherwise, print a blank line for empty children
else
{
if (p_root->p_left.get())
printTree(p_root->p_left, indentation + 1);
else
std::cout << '\n';
if (p_root->p_right.get())
printTree(p_root->p_right, indentation + 1);
else
std::cout << '\n';
}
}
Assuming that the code which is not included in your question is correct, there is only one issue that could pose a problem if more than one tree is built. The problem is that x is a global variable which your functions change as a side-effect. But if that x is not reset before creating another tree, things will go wrong.
It is better to make x a local variable, and pass it by reference.
A minor thing: don't use NULL but nullptr.
Below your code with that change and the class definition included. I also include a printSideways function, which makes it easier to see that the tree has the expected shape:
#include <iostream>
using namespace std;
class Node {
public:
int m_Data;
Node* m_Left = nullptr;
Node* m_Right = nullptr;
Node(int v) : m_Data(v) {}
};
// Instead of si, accept x by reference:
Node* createTree(string str, int &x, int ei)
{
if (x >= ei)
return nullptr;
Node *root = new Node((str[x] - '0'));
if(str[x] != '0')
{
root->m_Data = (str[x] - '0');
x++;
return root;
}
if(str[x]=='0')
{
x++;
root->m_Left = createTree(str,x,ei);
root->m_Right = createTree(str,x,ei);
}
return root;
}
// Overload with a wrapper that defines x
Node* createTree(string str)
{
int x = 0;
return createTree(str, x, str.length());
}
// Utility function to visualise the tree with the root at the left
void printSideways(Node *node, string tab) {
if (node == nullptr) return;
printSideways(node->m_Right, tab + " ");
cout << tab << node->m_Data << "\n";
printSideways(node->m_Left, tab + " ");
}
// Wrapper for above function
void printSideways(Node *node) {
printSideways(node, "");
}
int main ()
{
string str = "050067089";
Node *node = createTree(str);
printSideways(node);
return 0;
}
So, as you see, nothing much was altered. Just si was replaced with x, which is passed around by reference, and x is defined locally in a wrapper function.
Here is the output:
9
0
8
0
7
0
6
0
5

c++ function return the smallest positive integer in a vector

I am using this code below which returns the smallest positive integer in a vector. I got the code here. My question is there a reason to pass the size to the function, can you not calculate it in the function body?
Also what is the second if() testing for? I can't understand how this if statement works?
#include <vector>
using namespace std;
int rec_min_pos(const vector<int> & nums, int size) {
if (size < 1) {
return INT_MAX;
}
if(nums[size-1] > 0){
return min(nums[size-1], rec_min_pos(nums, size-1));
}
else{
return rec_min_pos(nums, size-1);
}
}
The second if statement checks for positivity of the element, since the function shall return the minimum positive integer.
Your function is recursive and the 'size' argument is actually one plus the index to the last element to be tested. This allows a simple recursive function design, but requires an additional argument. It's presumably better to make these points explicit in the function interface
inline int recursive_min_positive(const int*arr, size_t i)
{
return
i==0? std::numeric_limits<int>::max() :
arr[i-1]<=0? recursive_min_positive(arr,i-1) :
std::min(arr[i-1],recursive_min_positive(arr,i-1) ;
}
int min_positive(std::vector<int> const&arr)
{
return recursive_min_positive(arr.data(), arr.size());
}
Recursive function design is often elegant, but inefficient (though compilers tend to unroll the recursion). Here, a non-recursive implementation is actually shorter and clearer.
int min_positive(std::vector<int> const&arr)
{
int result = std::numeric_limits<int>::max();
for(auto val : arr)
if(0 < val && val < result) result = val;
return result;
}
In addition to all comments: you can overload the function like this:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// Original function with size argument
int rec_min_pos(const vector<int> & nums, int size) {
if (size < 1) {
return INT_MAX;
}
if (nums[size - 1] > 0) {
return min(nums[size - 1], rec_min_pos(nums, size - 1));
}
else {
return rec_min_pos(nums, size - 1);
}
}
// Overloaded rec_min_pos function
int rec_min_pos(const vector<int> & nums) {
// here we just call the original rec_mon_pos function
return rec_min_pos(nums, nums.size());
}
int main()
{
vector<int> v{ 9,2,7,3,7,5,6 };
cout << rec_min_pos(v); // call the overloaded function
}
Output:
2
Not related to the recursive function, but expanding on my comment:
int min_positive(std::vector<int> & nums)
{
auto elem = std::min_element(nums.begin(), nums.end(),
[](int lhs, int rhs){ return std::tie(std::signbit(lhs), lhs) < std::tie(std::signbit(rhs), rhs); }
);
if ((elem == nums.end()) || std::signbit(*elems)) { return MAX_INT; }
return *elem;
}
Here we define a comparison function that orders positive before negative, and then by value. We use the three argument std::min_element, which will find us an iterator in nums.
The first check handles an empty nums, and the second one where every value is negative, both of which the original ignores, returning MAX_INT

Recursive function to get a decimal number out of a list of binaries

If I have a list with N elements that represent a binary number, and each node (I named it info) is a boolean (true = 1, false = 0) what would the best way to get the decimal value using a recursive function be?
I tried using google but I only came with the formula for decimal;
1 * 2N + 0 * 2N-1 + 0 * 2N-2 + ... + 1 * 21 + 1 * 20
Right now I have a header and some basic structure for the method, according to what I understand of the problem. Also the problem says the first digit is the most significative but I don´t quite get if that is relevant.
int Lista:: ConvierteBinarioDecimal ( void ) const;
static int suma= 0;
ConvierteBinarioDecimal();
}
return suma;
}
And the Nodo (node) class.
class Nodo{
public:
bool Nodo::getInfo(void); //Retorns the content of info
Nodo* Nodo::getNext(void); //Retorns the cotent of next
private:
bool info;
Nodo *next;
};
class Lista{
Nodo *primero;
int longitud;
};
I started learning C++ last week and so far it has been way more tough than Java >_< so any help would be a godsend.
This is a recursive example:
I have to do some little changes, adding const to getInfo (there is no problem here) and adding const to getNext (you could need also and non-const version), the problem was that function ConvierteBinarioDecimal is declared as const which is good (don't have to change anything for calculating decimal representation, but this force, that the two method need to be const) you could add non-const version if needed.
The static int ConvierteBinarioDecimal(Nodo const* node) { is the recursive implementation of the conversion to decimal from binary. If it need to be recursive this is your sample code, if you could use an iterative version would be better for performance.
#include <algorithm>
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
class Nodo {
public:
bool getInfo(void) const { return info; } // Retorns the content of info
Nodo* getNext(void) const { return next; } // Retorns the cotent of next
Nodo(bool i, Nodo* n) : info(i), next(n) {}
private:
bool info;
Nodo* next;
};
class Lista {
Nodo* primero;
int longitud;
public:
int ConvierteBinarioDecimal(void) const;
Lista(Nodo* p, int l) : primero(p), longitud(l) {}
};
static int ConvierteBinarioDecimal(Nodo const* node, int decimal = 0) {
if (node == NULL) // prefer C++11 nullptr
return decimal;
decimal *= 2;
if (node->getInfo())
decimal++;
return ConvierteBinarioDecimal(node->getNext(), decimal);
}
int Lista::ConvierteBinarioDecimal(void) const {
return ::ConvierteBinarioDecimal(primero);
}
int main(int argc, char* argv[]) {
Lista list(new Nodo(true, new Nodo(false, new Nodo(true, new Nodo(true, NULL)))), 4);
std::cout << list.ConvierteBinarioDecimal() << std::endl;
return 0;
}
ConvierteBinarioDecimal()
{
int indice = longitud;
Nodo *corriente = primero; // current, begin at first node
while (corriente != null)
{
if (corriente->getInfo())
suma += 1 << --indice; // use bitshifting to add this binary digit
// alternatively, this could be "suma |= 1 << --indice;"
corriente = corriente->getNext(); // go to next node
}
}
I hope the Spanish helps as well! :)
One of the fastest ways to do this is to use bit shift operations. So, for example:
long decimal = 0;
Nodo * current = primero;
unsigned int bitcounter = 0;
while(current)
{
if(current->getInfo)
{
long temp = 1;
temp << bit counter;
decimal |= temp;
}
bitcounter++;
current = current->next;
}
Basically, what I've done here is to look at each bit in a while look. Note how I traverse the linked list. I stop when current->next is null by checking current in the following iteration. I also keep track of which bit I'm processing. For each bit, if the bit is 1, I place that into a temporary variable and shift it over to the right position using the << operator. Then I OR this temporary variable with the running total using the |= operator (OR and assignment).
Now, to do this recursively:
long ConvertBinaryToDecimal()
{
static long decimal = 0;
static Nodo * current = primero;
// Base case
if(!current)
{
current = primero;
long result = decimal;
decimal = 0;
return result;
}
else {
decimal = decimal<<1;
if(primero->getInfo())
decimal |= 1;
current = current->next;
ConvertBinaryToDecimal();
}

How to sort a Vector of type <class*>? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C++ how to sort vector<class *> with operator <
Hello everyone!
Please i am trying to sort a vector of type "class" based on one of its data members. As follows:
The Header File: (Undirected_Graph.h)
#ifndef UNDIRECTED_GRAPH_H
#define UNDIRECTED_GRAPH_H
#include <vector>
using std::vector;
#include <climits>
class Edge;
class Node
{
public:
Node(int); //The constructor.
int id; //For the id of the node.
bool visited; //For checking visited nodes.
int distance;
vector <Edge*> adj; //The adjacent nodes.
};
class Edge
{
public:
Edge(Node*, Node*, int); //The constructor.
Node* start_Node; //The start_Node start of the edge.
Node* end_Node; //The end of the edge.
int w; //The weight of the edge.
bool isConnected(Node* node1, Node* node2) //Checks if the nodes are connected.
{
return((node1 == this->start_Node && node2 == this->end_Node) ||
(node1 == this->end_Node && node2 == this->start_Node));
}
};
class Graph
{
public:
Graph(int); //The Constructor.
int max_Nodes; //Maximum Number of allowed Nodes.
vector <Edge*> edges_List; //For storing the edges of the graph.
vector <Node*> nodes_List; //For storing the nodes of the graph.
void insertEdge(int, int, int);
int getNumNodes();
int getNumEdges();
};
#endif
The Implementation File: (Undirected_Graph.cpp)
#include "Undirected_Graph.h"
Node::Node(int id_Num)
{
id = id_Num;
visited = 0;
distance = INT_MAX;
}
Edge::Edge(Node* a, Node* b, int weight)
{
start_Node = a;
end_Node = b;
w = weight;
}
Graph::Graph(int size)
{
max_Nodes = size;
for (int i = 1; i <= max_Nodes; ++i)
{
Node* temp = new Node(i);
nodes_List.push_back(temp);
}
}
void Graph::insertEdge(int x, int y, int w)
{
Node* a = nodes_List[x-1];
Node* b = nodes_List[y-1];
Edge* edge1 = new Edge(a, b, w);
Edge* edge2 = new Edge(b, a, w);
edges_List.push_back(edge1);
a->adj.push_back(edge1);
b->adj.push_back(edge2);
}
int Graph::getNumNodes()
{
return max_Nodes;
}
int Graph::getNumEdges()
{
return edges_List.size();
}
Now in the above code, after creating several nodes and edges, i need to sort the edges of this graph based on their weight. I am studying a way to implement Kruskal algorithm so i though of sorting the edges first based on their weight.
sort (myGraph.edges_List[index].begin(), myGraph.edges_List[index].end());
obviously does not work! since the vector edges_List is of type "Edge".
Assuming that (myGraph is an object of the class).
I was wondering if there is any good technique to do that?
Thanks in advance for your help! Any suggestions or ideas are greatly appreciated!
By default, std::sort uses using operator<, but you can also supply a comparison function object.
So:
bool your_comparer(const Edge * left, const Edge * right)
{
// return true if left should come before right, false otherwise
}
// ...
sort (myGraph.edges_List.begin(), myGraph.edges_List.end(), your_comparer);
Another way is usage std::set container for storing your objects. And you always will have sorted container. All you need is define operator < for stored classes.
Usage vector with push_back is not effective way in terms of time. It cause unnecessary memory rellocations.

Priority Queue Wrong Order

I am programming the huffman encoding. This is the beginning of my program:
using namespace std;
//Counting methods
int *CountCharOccurence(string text)
{
int *charOccurrence = new int[127];
for(int i = 0; i < text.length(); i++)
{
charOccurrence[text[i]]++;
}
return charOccurrence;
}
void DisplayCharOccurence(int *charOccurrence)
{
for(int i = 0; i < 127; i++)
{
if(charOccurrence[i] > 0)
{
cout << (char)i << ": " << charOccurrence[i] << endl;
}
}
}
//Node struct
struct Node
{
public:
char character;
int occurrence;
Node(char c, int occ) {
character = c;
occurrence = occ;
}
bool operator < (const Node* node)
{
return (occurrence < node->occurrence);
}
};
void CreateHuffmanTree(int *charOccurrence)
{
priority_queue<Node*, vector<Node*> > pq;
for(int i = 0; i < 127; i++)
{
if(charOccurrence[i])
{
Node* node = new Node((char)i, charOccurrence[i]);
pq.push(node);
}
}
//Test
while(!pq.empty())
{
cout << "peek: " << pq.top()->character << pq.top()->occurrence << endl;
pq.pop();
}
}
int main(int argc, char** argv) {
int *occurrenceArray;
occurrenceArray = CountCharOccurence("SUSIE SAYS IT IS EASY");
DisplayCharOccurence(occurrenceArray);
CreateHuffmanTree(occurrenceArray);
return (EXIT_SUCCESS);
}
The program first outputs the characters with their occurence number. This looks fine:
: 4
A: 2
E: 2
I: 3
S: 6
T: 1
U: 1
Y: 2
but the test loop which has to display the node contents in priority order outputs this:
peek: Y2
peek: U1
peek: S6
peek: T1
peek: I3
peek: E2
peek: 4
peek: A2
This is not the expected order. Why?
Elements in your priority queue are pointers. Since you don't provide a function that takes 2 pointers to Node objects , default compare function compares 2 pointers.
bool compareNodes(Node* val1, Node* val2)
{
return val1->occurence < val2->occurence;
}
priority_queue<Node*, vector<Node*>,compareNodes > pq;
Your operator < is used when Node compares with Node*
You should tell your priority queue what it should sort by. In your case, you have to tell it to sort by Node::occurence.
You are storing pointers to nodes in the queue, but haven't provided a suitable comparison function, so they are sorted by comparing the pointers. The operator< you've provided will compare a node with a pointer, which isn't what you want.
There are two options:
Provide a function for comparing two node pointers according to their values, and give this function to the queue, or
Store node objects in the queue, and provide an operator< to compare two nodes.
The second option will also fix the memory leak in your code, and remove a whole pile of unnecessary memory allocations, so I would suggest that.