I have the following program.What is the best , and most efficient way to check if the two stacks are equal by the values they contain?
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
struct StackNode
{
int data;
StackNode* next;
};
StackNode* newNode(int data)
{
StackNode* stackNode = new StackNode[sizeof(StackNode)];
stackNode->data = data;
stackNode->next = NULL;
return stackNode;
}
int isEmpty( StackNode *root)
{
return !root;
}
void push( StackNode** root, int data)
{
StackNode* stackNode = newNode(data);
stackNode->next = *root;
*root = stackNode;
}
int pop( StackNode** root)
{
if (isEmpty(*root))
return INT_MIN;
StackNode* temp = *root;
*root = (*root)->next;
int popped = temp->data;
free(temp);
return popped;
}
int peek(StackNode* root)
{
if (isEmpty(root))
return INT_MIN;
return root->data;
}
bool AreEqual(StackNode** lhs, StackNode** rhs)
{
////// ?
}
int main()
{
StackNode* root = NULL;
StackNode * r2 = NULL;
push(&root, 10);
push(&root, 20);
push(&root, 30);
push(&r2, 123);
push(&r2, 1231213);
AreEqual(&root, &r2);
}
if the stacks contains equivalent numbers but in different order , then the method should return true .. I would be very thankful if you could give me some directions for that task.Thanks in advice.
Considering
if the stacks contains equivalent numbers but in different order , then the method should return true
I think the optimal solution would be via sort and compare.
Extract the data from each stack
k1 = {data of lhs} -> O(n)
k2 = {data of rhs} -> O(n)
Sort the two arrays
k1_sorted = sort(k1) -> O(n log(n))
k2_sorted = sort(k2) -> O(n log(n))
Now you can compare the two sorted arrays in O(n). Keep in mind the possible repeated numbers in k1_sorted and k2_sorted.
As well as the sort method, you could take a counting approach:
#include <string>
#include <iostream>
#include <vector>
#include <map>
/**
* Returns true iff the two vectors contain the same elements
* (including number of duplicates) in any order.
*
* Alternatively std::sort both vectors and just compare them
* for equality, which may or may not be faster.
*/
bool sortOfEquivalent(const std::vector<int>& lhs, const std::vector<int>& rhs)
{
std::map<int, std::pair<int,int>> accumulator;
for (const auto x : lhs) {
accumulator[x].first++;
}
for (const auto x : rhs) {
accumulator[x].second++;
if (accumulator[x].second > accumulator[x].first) {
// Can bail early here; the RHS already has
// more x's than the LHS does
return false;
}
}
for (const auto& y : accumulator) {
if (y.second.first != y.second.second)
return false;
}
return true;
}
int main()
{
std::vector<int> lhs{3,5,5,7,1};
std::vector<int> rhs{1,2,3,4,5,6,7};
std::cout << sortOfEquivalent(lhs, rhs);
}
Depending on your data, this may or may not be faster than the sorting method. It also may or may not take less storage than the sorting method.
Also in reality you'd probably take a reference to accumulator[x] in that second loop rather than looking up the element three times.
However, you can only apply this solution to your situation if you treat your stack as not-a-stack, i.e. using its underlying data store (forward iteration is required). This may or may not be permitted.
On the outside your functions handle a stack, but the actual structure you implement the stack in is a simple linked list.
And comparing two linked lists is done by comparing each element one by one, stopping when either list runs out or you find a difference in the elements.
Related
I am trying to implement my own priority queue that does the same thing as the standard priority queue from STL. The elements from queue have to respect an order, and for this I used a compare function. For this case the elements from queue are sorted ascending by their frequency and the compare function returns the difference between 2 elements' frequency. If the difference is less than 0, we found the place where the element should be inserted, otherwise the iteration continues.
My struggle is that the compare function always returns the value 0 regardless of difference between frequences (eg if one element has frequency equals to 2 and other has it equals to 3, their difference if -1, but relation function will return 0).
Here is the source code:
#pragma once
#include"BinaryTree.h"
typedef int(*TRelation)(const BinaryTree& bt1, const BinaryTree& bt2);
inline int getPriority(const BinaryTree& bt1, const BinaryTree& bt2) {
return bt1.getFrequence() - bt2.getFrequence();
}
class PriorityQueue {
TRelation relation;
BinaryTree* first;
public:
PriorityQueue() {
relation = getPriority;
first = nullptr;
}
void add(BinaryTree* e) {
if (first == nullptr) {
first = e;
return;
}
//add at start
if (relation(*e, *first)<0)
{
BinaryTree *aux= first;
first = e;
e->next = aux;
return;
}
BinaryTree *pre=first ;
BinaryTree *current = first;
while (current!=nullptr && relation(*e, *current)>=0) {
pre = current;
current = current->next;
}
pre->next = e;
e->next = current;
}
I also tried different implementation of getPriority() function like changing its returning type, elements' type, etc.
I have a TrieNode class defined as follows:
class TrieNode {
public:
map<char, TrieNode*> children;
bool isLeaf = false; // if node represents end of word
int wordCount = 0; // How many times the word appears
TrieNode();
};
I'm trying to print out all of the words in the trie (preferably in alphabetical order, although I'd settle for anything at this point). I've been trying to implement a recursive solution, but I haven't been able to make a decent start.
EDIT: I should mention that all the other questions I've looked at for how to print all words in a trie store children as an array, rather than a map.
Here's a depth-first recursive traversal.
It would be best not to use raw pointers, but I did it here because you asked and I like you.
I did not delete the child nodes allocated by AddTrie, because I just wanted to demonstrate the traversal, rather than write an entire implementation.
So, you need to add code to delete these if you use this.
#include <iostream>
#include <map>
#include <string>
class TrieNode {
public:
std::map<char, TrieNode*> children;
bool isLeaf = false; // if node represents end of word
int wordCount = 0; // How many times the word appears
TrieNode() {}
};
void AddTrie(TrieNode& trie, const char* word) {
auto c = *(word++);
auto next = trie.children[c];
if(!next) { trie.children[c] = next = new TrieNode; }
if(*word) { AddTrie(*next, word); }
else { next->isLeaf = true; }
}
void DumpTrie(const TrieNode& trie, std::string word={}) {
for(const auto& child : trie.children) {
const auto next_word = word + child.first;
if(child.second->isLeaf) { std::cout << next_word << '\n'; }
DumpTrie(*child.second, next_word);
} }
int main() {
TrieNode trie;
AddTrie(trie, "goodbye");
AddTrie(trie, "hello");
AddTrie(trie, "good");
AddTrie(trie, "goodyear");
DumpTrie(trie);
}
Output
good
goodbye
goodyear
hello
I assume you want to waste less memory than a 26 slot array in each node by using a map instead? But seeing how maps initial construction cost is pretty high you might want to use a mutual map for all nodes instead of storing one in each node.
I want to insert new (unique) element into known place (generally somewhere in the middle) of an ordered associative container std::set/std::multiset/std::map/std::multimap using insert (w/ hint) or emplace_hint.
During insertion operation I absolutely sure, that the place to insert is right before the "hint" iterator. Generally I can compare any two non-neighbouring elements in the container, but this operation is strongly heavyweight. To avoid overhead imposed, I provide custom comparator for the container, which contains a references to pointers to both neigbouring elements (they always became known right before the insertion/emplacement operation).
#include <map>
#include <set>
static std::size_t counter = 0;
template< typename T >
struct less
{
T const * const & pl;
T const * const & pr;
bool operator () (T const & l, T const & r) const
{
if (&l == &r) {
return false;
}
if (pl) {
if (&l == pl) {
return true;
}
if (&r == pl) {
return false;
}
}
if (pr) {
if (&r == pr) {
return true;
}
if (&l == pr) {
return false;
}
}
++counter;
return l < r; // very expensive, it is desirable this line to be unrecheable
}
};
#include <iostream>
#include <algorithm>
#include <iterator>
#include <cassert>
int main()
{
using T = int;
T const * pl = nullptr;
T const * pr = nullptr;
less< T > less_{pl, pr};
std::set< T, less< T > > s{less_};
s.insert({1, 2,/* 3, */4, 5});
std::copy(std::cbegin(s), std::cend(s), std::ostream_iterator< T >(std::cout, " "));
std::cout << '\n';
auto const hint = s.find(4);
// now I want to insert 3 right before 4 (and, of course, after 2)
pl = &*std::prev(hint); // prepare comparator to make a cheap insertion
pr = &*hint;
// if hint == std::end(s), then pr = nullptr
// else if hint == std::begin(s), then pl = nullptr
// if I tried to insert w/o hint, then pl = pr = nullptr;
{
std::size_t const c = counter;
s.insert(hint, 3);
assert(counter == c);
}
std::copy(std::cbegin(s), std::cend(s), std::ostream_iterator< T >(std::cout, " "));
std::cout << '\n';
}
Current libc++/libstdc++ implementations allows me to use described comparator, but is there undefined behaviour if I rely on their current behaviour? Can I rely, that insert (w/ hint parameter) or emplace_hint (and modern insert_or_assign/try_emplace w/ hint parameter for map/multimap) don't touch any other elements other then pointed by pl and pr? Is it implementation-defined thing?
Why I want this strange thing? IRL I tried to implement Fortune's algorithm to find Voronoi diagram on the plane using native STL's self-balanced binary search tries. std::set is used to store current state of a part of a so-called beach line: a chain of sorted endpoints. When I add a new endpoint I always know the place where to insert it right before the insertion. It would be best if I can add assert(false); before or throw std::logic_error{};/__builtin_unreachable(); instead of last return in comparator functor. I only can do it if there is corresponding logical guarantee. Can I do this?
I wonder if anybody could help me out.
I look for a data structure (such as list, queue, stack, array, vector, binary tree etc.) supporting these four operations:
isEmpty (true/false)
insert single element
pop (i.e. get&remove) single element
split into two structures e.g. take a approximately half (let's say +/- 20%) of elements and move them to another structure
Note that I don't care about order of elements at all.
Insert/pop example:
A.insert(1), A.insert(2), A.insert(3), A.insert(4), A.insert(5) // contains 1,2,3,4,5 in any order
A.pop() // 3
A.pop() // 2
A.pop() // 5
A.pop() // 1
A.pop() // 4
and the split example:
A.insert(1), A.insert(2), A.insert(3), A.insert(4), A.insert(5)
A.split(B)
// A = {1,4,3}, B={2,5} in any order
I need the structure to be be fast as possible - preferably all four operations in O(1). I doubt it have been already implemented in std so I will implement it by myself (in C++11, so std::move can be used).
Note that insert, pop and isEmpty are called about ten times more frequently than split.
I tried some coding with list and vector but with no success:
#include <vector>
#include <iostream>
// g++ -Wall -g -std=c++11
/*
output:
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
5 6 7 8 9
*/
int main ()
{
std::vector<int> v1;
for (int i = 0; i < 10; ++i) v1.push_back(i);
for (auto i : v1) std::cout << i << " ";
std::cout << std::endl;
auto halfway = v1.begin() + v1.size() / 2;
auto endItr = v1.end();
std::vector<int> v2;
v2.insert(v2.end(),
std::make_move_iterator(halfway),
std::make_move_iterator(endItr));
// sigsegv
/*
auto halfway2 = v1.begin() + v1.size() / 2;
auto endItr2 = v1.end();
v2.erase(halfway2, endItr2);
*/
for (auto i : v1) std::cout << i << " ";
std::cout << std::endl;
for (auto i : v2) std::cout << i << " ";
std::cout << std::endl;
return 0;
}
Any sample code, ideas, links or whatever useful? Thanks
Related literature:
How to move the later half of a vector into another vector? (actually does not work due to deletetion problem)
http://www.cplusplus.com/reference/iterator/move_iterator/
Your problems with the deletion aare due to a bug in your code.
// sigsegv
auto halfway2 = v1.begin() + v1.size() / 2;
auto endItr2 = v1.end();
v2.erase(halfway2, endItr2);
You try to erase from v2 with iterators pointing into v1. That won't work and you probably wanted to callerase on v1.
That fixes your deletion problem when splitting the vector, and vector seems to be the best container for what you want.
Note that everything except split can be done in O(1) on a vector if you insert at the end only, but since order doesn't matter for you I don't see any problem with it, split would be O(n) in your implemention once you fixed it, but that should be pretty fast since the data is right next to eachother in the vector and that's very cache friendly.
I can’t think of a solution with all operations in O(1).
With a list you can have push and pop in O(1), and split in O(n) (due to the fact that you need to find the middle of the list).
With a balanced binary tree (not a search tree) you can have all operations in O(log n).
edit
There have been some suggestions that keeping the middle of the list would produce O(1). This is not the case as when you split the function you have to compute the middle of the left list and the middle of the right list resulting in O(n).
Some other suggestion is that a vector is preferred simply because it is cache-friendly. I totally agree with this.
For fun, I implemented a balanced binary tree container that performs all operations in O(log n). The insert and pop are obviously in O(log n). The actual split is in O(1), however we are left with the root node which we have to insert in one of the halves resulting in O(log n) for split also. No copying is involved however.
Here is my attempt at the said container (I haven’t thoroughly tested for correctness, and it can be further optimized (like transforming the recursion in a loop)).
#include <memory>
#include <iostream>
#include <utility>
#include <exception>
template <class T>
class BalancedBinaryTree {
private:
class Node;
std::unique_ptr<Node> root_;
public:
void insert(const T &data) {
if (!root_) {
root_ = std::unique_ptr<Node>(new Node(data));
return;
}
root_->insert(data);
}
std::size_t getSize() const {
if (!root_) {
return 0;
}
return 1 + root_->getLeftCount() + root_->getRightCount();
}
// Tree must not be empty!!
T pop() {
if (root_->isLeaf()) {
T temp = root_->getData();
root_ = nullptr;
return temp;
}
return root_->pop()->getData();
}
BalancedBinaryTree split() {
if (!root_) {
return BalancedBinaryTree();
}
BalancedBinaryTree left_half;
T root_data = root_->getData();
bool left_is_bigger = root_->getLeftCount() > root_->getRightCount();
left_half.root_ = std::move(root_->getLeftChild());
root_ = std::move(root_->getRightChild());
if (left_is_bigger) {
insert(root_data);
} else {
left_half.insert(root_data);
}
return std::move(left_half);
}
};
template <class T>
class BalancedBinaryTree<T>::Node {
private:
T data_;
std::unique_ptr<Node> left_child_, right_child_;
std::size_t left_count_ = 0;
std::size_t right_count_ = 0;
public:
Node() = default;
Node(const T &data, std::unique_ptr<Node> left_child = nullptr,
std::unique_ptr<Node> right_child = nullptr)
: data_(data), left_child_(std::move(left_child)),
right_child_(std::move(right_child)) {
}
bool isLeaf() const {
return left_count_ + right_count_ == 0;
}
const T& getData() const {
return data_;
}
T& getData() {
return data_;
}
std::size_t getLeftCount() const {
return left_count_;
}
std::size_t getRightCount() const {
return right_count_;
}
std::unique_ptr<Node> &getLeftChild() {
return left_child_;
}
const std::unique_ptr<Node> &getLeftChild() const {
return left_child_;
}
std::unique_ptr<Node> &getRightChild() {
return right_child_;
}
const std::unique_ptr<Node> &getRightChild() const {
return right_child_;
}
void insert(const T &data) {
if (left_count_ <= right_count_) {
++left_count_;
if (left_child_) {
left_child_->insert(data);
} else {
left_child_ = std::unique_ptr<Node>(new Node(data));
}
} else {
++right_count_;
if (right_child_) {
right_child_->insert(data);
} else {
right_child_ = std::unique_ptr<Node>(new Node(data));
}
}
}
std::unique_ptr<Node> pop() {
if (isLeaf()) {
throw std::logic_error("pop invalid path");
}
if (left_count_ > right_count_) {
--left_count_;
if (left_child_->isLeaf()) {
return std::move(left_child_);
}
return left_child_->pop();
}
--right_count_;
if (right_child_->left_count_ == 0 && right_child_->right_count_ == 0) {
return std::move(right_child_);
}
return right_child_->pop();
}
};
usage:
BalancedBinaryTree<int> t;
BalancedBinaryTree<int> t2;
t.insert(3);
t.insert(7);
t.insert(17);
t.insert(37);
t.insert(1);
t2 = t.split();
while (t.getSize() != 0) {
std::cout << t.pop() << " ";
}
std::cout << std::endl;
while (t2.getSize() != 0) {
std::cout << t2.pop() << " ";
}
std::cout << std::endl;
output:
1 17
3 37 7
If the number of elements/bytes stored at any one time in your container is large, the solution of Youda008 (using a list and keeping track of the middle) may not be as efficient as you hope.
Alternatively, you could have a list<vector<T>> or even list<array<T,Capacity>> and keep track of the middle of the list, i.e. split only between two sub-containers, but never split a sub-container. This should give you both O(1) on all operations and reasonable cache efficiency. Use array<T,Capacity> if a single value for Capacity serves your needs at all times (for Capacity=1, this reverts to an ordinary list).
Otherwise, use vector<T> and adapt the capacity for new vectors according to demand.
bolov's points out correctly that finding the middles of the lists emerging from splitting one list is not O(1). This implies that keeping track of the middle is not useful. However, using a list<sub_container> is still faster than list, because the split only costs O(n/Capacity) not O(n). The price you pay for this is that the split has a graininess of Capacity rather than 1. Thus, you must compromise between the accuracy and cost of a split.
Another option is to implement own container using a linked list and a pointer to that middle element, at which you want to split it. This pointer will be updated on every modifying operation. This way you can achieve O(1) complexicity on all operations.
I have a vector that that stores Node*. A Node has the member properties:row,col,value. In my vector, I have gotten it to where all the Nodes* within the same row but not necessarily in correct column order. So basically I want to sort it so it's truly in row-major form. Right now, the columns are out of order within each "row". I appreciate any help you could give!
Edit:
Here is the method I have that is sorting my vector by row. Is there a way to additionally sort the columns as well?
vector<Node*> vect;
int i,j,minIndex;
Node* temp = new Node(NULL,NULL,0,0,0);
for(i=0;i<vect.size()-1;i++)
{
minIndex = i;
for(j=i+1;j<vect.size();j++)
{
if(vect.at(j)->row<vect.at(minIndex)->row)
{
minIndex = j;
}
}
if(minIndex!=i)
{
temp = vect.at(i);
vect.at(i) = vect.at(minIndex);
vect.at(minIndex) = temp;
}
}
You don't really need to implement your own sorting algorithm here. You can just use the standard template library's sort() method and then override default the behavior for sorting your Node* vector.
// This returns true if Node* a should be considered "less than" Node* b.
struct less_node : binary_function <Node*,Node*,bool>
{
bool operator() (const Node*& a, const Node*& b) const
{
// sort by row first
if (a->row < b->row)
return true;
// then sort by col within each row
if (a->row == b->row && a->col < b->col)
return true;
return false;
}
};
Once you have this less_node structure defined, you would just call:
sort(vect.begin(), vect.end(), less_node());