vector sort - c++ - c++

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

Related

Inline function always returns the same value

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.

Comparing stack data structure c++

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.

How to do InOrder traversal with B-Tree?

struct BTreeNode {
bool is_leaf=true;
std::vector<int> elements;
std::vector<BTreeNode*> children;
BTreeNode() {}
BTreeNode (std::vector<int> v) {
this->elements = v;
}
};
void traverse(BTreeNode* root) {
for(int i = 0; i < (int)root->children.size(); ++i){
traverse(root->children[i]);
cout << root->elements[i] << endl;
}
traverse(root->children[root->children.size() -1]);
}
My method somehow segfaults. How do we write a correct inOrder Traversal for B-Tree?
It's probably the last traverse call when you are at a leaf. I don't think that this traverse is needed.
Assuming BTreeNode is a generic definition of your b-tree node, whereas T1 is the type of the keys and T2 is the type of the values in the tree, and sortedKeys is the list you are after, you can use the following recursive method. The idea is very similar to an inOrder traversal in binary search tree, first visit the left-most child, then visit the key- then continue, Since the number of children in B-tree is always one bigger than the number of keys, a check is needed before visiting the key [code is in c#, but can easily be converted to any other language, the purpose is to show the algorithm only].
public void InOrderTraversal(BTreeNode<T1, T2> node, List<KeyValuePair<T1, T2>> sortedKeys)
{
if (node != null)
{
for (int i = 0; i < node.Children.Count; i++)
{
InOrderTraversal(node.Children[i], sortedKeys);
if (i < node.KeyValues.Count)
sortedKeys.Add(node.KeyValues[i]);
}
}
}

How to replace std::vector by linked list?

I have used std::vector for making my algorithm. I would like to replace the vectors by linked lists.
In order to do so, I was thinking of using the std::list, but I have no idea how to do this, for example I have tried following example for finding a value within a vector/list:
void find_values_in_vector(const std::vector<int>& input_vector, int value, int &rv1, int &rv2)
{
if (input_vector[0] >= value) { // too small
rv1 = 0; rv2 = 0; return;
}
int index = (int)input_vector.size() - 1;
if (input_vector[index] <= value) { // too big
rv1 = index; rv2 = index; return;
}
// somewhere inside
index = 0;
while (input_vector[index] <= value) {
index++;
}
rv1 = index - 1; rv2 = index; return;
}
void find_values_in_list(const std::list<int>& input_list, int value, int &rv1, int &rv2)
{
if (*input_list.begin() >= value) { // too small
rv1 = 0; rv2 = 0; return;
}
if (*input_list.end() <= value) { // too big
rv1 = (int)input_list.size() - 1; rv2 = (int)input_list.size() - 1; return;
}
// somewhere inside
int index = 0; int temp = *input_list.begin();
while (temp <= value) {
temp = *input_list.next(); index++;
}
rv1 = index - 1; rv2 = index; return;
}
This seems not to work, as the member function next() is not existing. However I remember that browsing through a linked list is done by going to the beginning, and moving further to the next element until the a certain point is reached. I have seen that there is a way to get this done by using an interator in a for-loop, but I wonder what's wrong with my approach? I was under the impression that a std::list was a standard implementation of a double-directional linked list, or am I wrong and in that case, what std class is the implementation of a linked list (it does not need to be a double-directional linked list)?
The standard way to iterate through containers is like this:
for(std::list<int>::iterator it = input_list.begin();
it != input_list.end();
it++)
{
....
}
This also works for vectors,maps,deque,etc. The Iterator concept is consistently implemented throughout the STL so it's best to get used to this concepts.
There are also iterator operations like std::distance and std::advance etc. for the different types of iterators (I suggest you read up on them and their advantages/limitations)
If you have C++ 11 available you can also use this syntax (may not be useful for your problem though.)
for(const auto& value : input_list)
{
...
}
This also works throughout the STL container.
This should work for vector, list, deque, and set (assuming the contents are sorted).
template <class T>
void find_values_in_container(const T& container, int value, int &rv1, int &rv2)
{
rv1 = rv2 = 0; // Initialize
if (container.empty() || container.front() >= value)
{
return;
}
for (const auto& v : container)
{
rv2++;
if (v > value)
{
break;
}
rv1++;
}
return;
}

the sequence of insert and erase using stl::list

When I am doing practice on leetcode, I met a problem like this:
I used a stl::list container as cache for LRU algorithm. But the sequence of erasing an item and inserting an item made the result different.
I know that it is actually a double list as stl::list. And the sequence of inserting and erasing should not matter when I use iterator.
The code is here
class LRUCache{
public:
map<int, list<pair<int,int>>::iterator> mKey;
list<pair<int,int>> lCache;
int cap;
LRUCache(int capacity) {
cap = capacity;
}
int get(int key) {
auto iter = mKey.find(key);
if(iter != mKey.end()) {
int value = (iter->second)->second;
//**the sequence of next two lines can not be changed!***
lCache.erase(iter->second);
mKey[key] = lCache.insert(lCache.begin(), make_pair(key,value));
return value;
}
return -1;
}
void set(int key, int value) {
auto iter = mKey.find(key);
if(iter == mKey.end()) {
if(lCache.size() < cap) {
mKey[key] = lCache.insert(lCache.begin(), make_pair(key,value));
}
else{
mKey[key] = lCache.insert(lCache.begin(), make_pair(key,value));
mKey.erase(lCache.back().first);
lCache.pop_back();
}
}
else {
lCache.erase(iter->second);
mKey[key] = lCache.insert(lCache.begin(), make_pair(key,value));
}
}
};
It's not quite clear what you are asking. If your question is why these two lines can't be reordered:
//**the sequence of next two lines can not be changed!***
lCache.erase(iter->second);
mKey[key] = lCache.insert(lCache.begin(), make_pair(key,value));
then that's simple. iter points to the same node as mKey[key], so the assignment actually changes the value of iter->second. If the assignment would happen first, then iter->second would point to the freshly inserted list node, not the previously existing one.