As C++'s std::partial_sort do. lsort is not powerful enough.
There is no built-in equivalent to partial_sort. I think your choices are either to implement it by hand in Tcl, which would probably undermine whatever efficiency you sought to gain; or write an extension that actually exposes partial_sort to the interpreter. That wouldn't be too difficult actually -- Tcl extensions are pretty easy to write. Here's a bit of code I just whipped up that should get you started:
#include <algorithm>
#include "tcl.h"
using namespace std;
static int PartialSortCommand(ClientData dummy,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]);
EXTERN int
Partialsort_Init(Tcl_Interp *interp)
{
if (Tcl_InitStubs(interp, "8.0", 0) == NULL) {
return TCL_ERROR;
}
if (Tcl_PkgProvide(interp, "partialsort", "1.0") != TCL_OK) {
return TCL_ERROR;
}
Tcl_CreateObjCommand(interp, "partialsort", PartialSortCommand,
(ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
return TCL_OK;
}
bool CompareObjs(Tcl_Obj *a, Tcl_Obj *b) {
int left, right;
Tcl_GetIntFromObj(0, a, &left);
Tcl_GetIntFromObj(0, b, &right);
return left < right;
}
int PartialSortCommand(
ClientData dummy,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[])
{
if (objc != 5) {
Tcl_WrongNumArgs(interp, 1, objv, "list start middle end");
return TCL_ERROR;
}
Tcl_Obj **objs;
int count;
if (Tcl_ListObjGetElements(interp, objv[1], &count, &objs) != TCL_OK) {
return TCL_ERROR;
}
int start, middle, end;
if (Tcl_GetIntFromObj(interp, objv[2], &start) != TCL_OK) {
return TCL_ERROR;
}
if (Tcl_GetIntFromObj(interp, objv[3], &middle) != TCL_OK) {
return TCL_ERROR;
}
if (Tcl_GetIntFromObj(interp, objv[4], &end) != TCL_OK) {
return TCL_ERROR;
}
partial_sort(&objs[start], &objs[middle], &objs[end], CompareObjs);
Tcl_SetObjResult(interp, Tcl_NewListObj(count, objs));
return TCL_OK;
}
Of course this is just a rough cut. It only handles lists of integers. It doesn't do much in the way of error checking. It's a bit cavalier with respect to shared Tcl_Obj structures. But hopefully it will get you going in the right directory.
Related
namespace std {
bool operator<(const vector<int>& v1, const vector<int>& v2)
{
if (v1[0] < v2[0] && v1[1] < v2[1])
return false;
else
return true;
}
}
int main() {
vector<vector<int>> a1{ {1,2},{3,4} };
sort(a1.begin(), a1.end());
for (auto num : a1)
cout << num[0] << num[1] << endl;
return 0;
}
why when I remove the namespace std, and it doesn't work anymore?It's about scope of sort?And why it does not need template specialisation?(just like here said enter link description here)
std::sort comes in two flavors. The first uses operator< to compare elements. The second takes a custom comparison predicate.
You probably want to use the second one here.
bool compare(const vector<int>& v1, const vector<int>& v2) noexcept
{
if (v1[0] < v2[0] && v1[1] < v2[1])
return false;
else
return true;
}
std::sort (a1.begin(), a1.end(), compare);
As for why your original code works only if you wrap it in namespace std, you need to read up on Argument Dependent Lookup
I have get the answer, the up one is not correct. The key of this question is sort only know functions in the std, just like this:
namespace mySpace {
void func()
{
cout << "my space" << endl;
}
void func2()
{
func();
}
}
using namespace mySpace;
void func() {
cout << "other " << endl;
}
int main() {
func2();
return 0;
}
In one of my classes at Uni we are creating Binary search trees and inserting data and looking them up. My code make sense in my head and because of this I cannot find the error anywhere. I have spent ages trying to find the error but cannot find it anywhere. The only thing that might be causing an error is that the precompiled headers didn't work when I started so i removed them from my project. The error only occurrs when i try to use the BST.Lookup and choose a key that is on the right subtree.
This is my main cpp file:
// BinarySearchTrees.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include "BST.h"
#include <iostream>
#include <fstream>
#include <string>
void ReadFile(BST &Bst)
{
int iKey;
std::string Key;
std::string Data;
std::ifstream testFile("Test.txt");
if (testFile.is_open())
{
while (!testFile.eof())
{
getline(testFile, Key, ' ');
getline(testFile, Data);
iKey = stoi(Key);
Bst.Insert(iKey, Data);
}
}
}
int main()
{
std::string Option;
int Choice;
BST BST;
//ReadFile(BST);
BST.Insert(6, "Oscar");
BST.Insert(20, "Ben");
BST.Insert(99, "James");
BST.Insert(1, "Alex");
while (Option != "exit")
{
std::cout << "If you wish to Lookup a Node, Insert value to find. Enter 'exit' to close" << std::endl;
getline(std::cin, Option);
if (Option == "exit")
break;
else
{
Choice = stoi(Option);
BST.Lookup(Choice);
}
}
return 0;
}
I believe that the readfile code may be incorrect but am unsure.
My Binary Search Tree Class:
#include "BST.h"
struct BST::Node {
Key key;
Item item;
Node* leftChild;
Node* rightChild;
Node(Key, Item);
};
void BST::Insert(Key inputKey, Item inputItem)
{
Node* previousNode = nullptr;
if (root == nullptr)
{
root = new Node(inputKey, inputItem);
}
else
{
InsertRec(inputKey, inputItem, root, previousNode);
}
}
void BST::InsertRec(Key inputKey, Item inputItem, Node* & Current, Node* & previousNode)
{
if (Current != nullptr)
{
previousNode = Current;
}
bool isLeft = false;
if (!isLeaf(Current))
{
if (inputKey > Current->key)
{
isLeft = false;
InsertRec(inputKey, inputItem, Current->rightChild, previousNode);
}
else if (inputKey < Current->key)
{
isLeft = true;
InsertRec(inputKey, inputItem, Current->leftChild, previousNode);
}
else
{
Current->item = inputItem;
}
}
else
{
Current = new Node(inputKey, inputItem);
if (isLeft)
{
previousNode->leftChild = Current;
}
else
{
previousNode->rightChild = Current;
}
}
}
BST::Item* BST::Lookup(Key soughtKey)
{
Item* Item = LookupRec(soughtKey, root);
std::string Display = /*std::to_string(soughtKey) + ": " + */ *Item;
std::cout << Display << std::endl;
return Item;
}
BST::Item* BST::LookupRec(Key soughtKey, Node* currentNode)
{
if (!isLeaf(currentNode))
{
if ((currentNode->key > soughtKey))
{
LookupRec(soughtKey, currentNode->leftChild);
}
else if ((currentNode->key < soughtKey))
{
LookupRec(soughtKey, currentNode->rightChild);
}
else
{
return ¤tNode->item;
}
}
else
{
return nullptr;
}
}
bool BST::isLeaf(Node* n)
{
if (nullptr == n)
{
return true;
}
else
{
return false;
}
}
BST::BST()
{
}
BST::Node::Node(Key K, Item I)
{
key = K;
item = I;
leftChild = nullptr;
rightChild = nullptr;
}
And finally my header file for the binary search tree:
#pragma once
#include "iostream"
#include "string"
class BST
{
public:
using Key = int;
using Item = std::string;
void Insert(Key, Item);
Item* Lookup(Key);
BST();
private:
struct Node;
Node* root = nullptr;
static bool isLeaf(Node*);
static Item* LookupRec(Key, Node*);
static void InsertRec(Key, Item, Node* &, Node* &);
};
Any help would be greatly appreciated. I've been stuck on this for too long and I cannot progress without fixing this first.
The Test.txt file is filled with keys and items that are read and inputted like how I do it manually at the start of my main function, so I dont think the error is the file data.
Thanks in advance
UPDATE: Have finally found the error. The problem was with the bool isLeft in my InsertRec function. The bool was always false due to the recursion so have changed the code to compare previousNode->Key with Current->Key to determine if the child goes left or right
I was implementing the ring buffer and have encountered an error. What does it mean to store a reference of outer class(class ring) object(m_ring) in inner class(class iterator) and when I remove the reference(&) the program compiles correctly but crashes. Please explain what is happening.(See the comment in Ring.h) Sorry for bad English.
// Ring.h
#ifndef RING.H
#define RING.H
#include <iostream>
using namespace std;
template<class T>
class ring {
unsigned int m_size;
int m_pos;
T *m_values;
public:
class iterator;
public:
ring(unsigned int size) : m_size(size), m_pos(0)
{
m_values = new T[m_size];
}
~ring()
{
delete[] m_values;
}
void add(const T &val)
{
m_values[m_pos] = val;
m_pos++;
m_pos %= m_size;
}
T& get(int pos)
{
return m_values[pos];
}
iterator begin()
{
return iterator(0, *this);
}
iterator end()
{
return iterator(m_size, *this);
}
};
template<class T>
class ring<T>::iterator {
int m_pos;
ring &m_ring; // Removing & gives garbage output.
public:
iterator(int pos, ring& aRing) : m_pos(pos), m_ring(aRing){}
bool operator!=(const iterator &other) const
{
return other.m_pos != m_pos;
}
iterator &operator++(int)
{
m_pos++;
return *this;
}
iterator &operator++()
{
m_pos++;
return *this;
}
T &operator*()
{
// return m_ring.m_values[m_pos];
return m_ring.get(m_pos);
}
};
#endif // RING
Driver program :
// Ring_Buffer_Class.cpp
#include <iostream>
#include "ring.h"
using namespace std;
int main()
{
ring<string> textring(3);
textring.add("one");
textring.add("two");
textring.add("three");
textring.add("four");
// C++ 98
for(ring<string>::iterator it = textring.begin(); it != textring.end(); it++)
{
cout << *it << endl;
}
cout << endl;
// C++11
for(string value : textring)
{
cout << value << endl;
}
return 0;
}
I also observed that removing ~ring() (Destructor) results into correct output.
Expected output :
four
two
three
four
two
three
I am implementing Graph for the first time and for that I took this problem from SPOJ.
Took help of geeksforgeeks, applied union find algorithm to find out whether or not graph contains a cycle but I get run time error (SIGSEGV).
Can you please help why is it so?
#include<iostream>
#include<stdlib.h>
#include<string.h>
using namespace std;
struct Edge{
int s,d;
};
struct Graph{
int v,e;
struct Edge* edge;
};
struct Graph* create(int v, int e){
struct Graph* graph=(struct Graph*)malloc(sizeof (struct Graph));
graph->v=v;
graph->e=e;
graph->edge=(struct Edge*)malloc(sizeof (struct Edge));
return graph;
};
int Find(int p[],int i)
{
if (p[i] == -1)
return i;
return Find(p, p[i]);
}
void Union(int p[],int i, int j)
{
p[j]=i;
}
bool CheckCycle(struct Graph* graph)
{
int *p=(int*)malloc(graph->v* sizeof (int));
memset(p,-1,graph->v * sizeof (int));
/*for(int i=0;i<graph->v;i++)
cout<<"p"<<i<<"="<<p[i];
cout<<"\n";*/
for(int i=0;i<graph->e;i++)
{
/*cout<<"edge"<<i<<" src="<<graph->edge[i].s<<"\n";
cout<<"edge"<<i<<" dest="<<graph->edge[i].d<<"\n";*/
int x=Find(p,graph->edge[i].s);
int y=Find(p,graph->edge[i].d);
/*cout<<"x="<<x<<" "<<"y="<<y<<"\n";*/
if(x==y)
return true;
Union(p,x,y);
}
return false;
}
int main()
{
ios_base::sync_with_stdio(false);
int N,M,v1,v2;
cin>>N>>M;
if(M!=(N-1))
cout<<"NO\n";
else{
struct Graph* graph=create(N,M);
for(int i=0;i<M;i++)
{
cin>>v1;
graph->edge[i].s=v1-1;
cin>>v2;
graph->edge[i].d=v2-1;
}
if(CheckCycle(graph))
cout<<"NO\n";
else
cout<<"YES\n";
}
}
One issue is this in your main program:
graph->edge[i].s=v1-1;
You created a single edge. If i is greater than 0, then this is an out-of-bounds access.
Look how you created edge in the create function:
graph->edge=(struct Edge*)malloc(sizeof (struct Edge));
That allocation holds a single edge, not multiple edges. Given how you coded the rest of your program in a C-like fashion, what you probably wanted is this:
graph->edge=(struct Edge*)malloc(sizeof(Edge) * e);
Also, you should strive to not use single-letter variable names. It is hard to read code with e, v, etc. as member variable names. Name those items m_edge, m_vertex or something that is more descriptive.
I didn't find it in Mac, but almost all Linux os support it..
Any one knows how to port it to mac?
Here is drop in replacement code. You should be able to put this in a header file and drop it in your project.
typedef int pthread_spinlock_t;
int pthread_spin_init(pthread_spinlock_t *lock, int pshared) {
__asm__ __volatile__ ("" ::: "memory");
*lock = 0;
return 0;
}
int pthread_spin_destroy(pthread_spinlock_t *lock) {
return 0;
}
int pthread_spin_lock(pthread_spinlock_t *lock) {
while (1) {
int i;
for (i=0; i < 10000; i++) {
if (__sync_bool_compare_and_swap(lock, 0, 1)) {
return 0;
}
}
sched_yield();
}
}
int pthread_spin_trylock(pthread_spinlock_t *lock) {
if (__sync_bool_compare_and_swap(lock, 0, 1)) {
return 0;
}
return EBUSY;
}
int pthread_spin_unlock(pthread_spinlock_t *lock) {
__asm__ __volatile__ ("" ::: "memory");
*lock = 0;
return 0;
}
See discussion, and Github source
EDIT: Here's a class that works on all OSes that includes a workaround for missing pthread spinlocks on OSX:
class Spinlock
{
private: //private copy-ctor and assignment operator ensure the lock never gets copied, which might cause issues.
Spinlock operator=(const Spinlock & asdf);
Spinlock(const Spinlock & asdf);
#ifdef __APPLE__
OSSpinLock m_lock;
public:
Spinlock()
: m_lock(0)
{}
void lock() {
OSSpinLockLock(&m_lock);
}
bool try_lock() {
return OSSpinLockTry(&m_lock);
}
void unlock() {
OSSpinLockUnlock(&m_lock);
}
#else
pthread_spinlock_t m_lock;
public:
Spinlock() {
pthread_spin_init(&m_lock, 0);
}
void lock() {
pthread_spin_lock(&m_lock);
}
bool try_lock() {
int ret = pthread_spin_trylock(&m_lock);
return ret != 16; //EBUSY == 16, lock is already taken
}
void unlock() {
pthread_spin_unlock(&m_lock);
}
~Spinlock() {
pthread_spin_destroy(&m_lock);
}
#endif
};
Try using OSSpinLock instead. Documentation is here: http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/spinlock.3.html
If the performance of your lock is not critical, pthread_mutex_t can be used as a drop replacement for pthread_spinlock_t, which makes porting easy.
I have used instead (that is natively supported by OS X intel)
pthread_rwlock_t lock;
pthread_rwlock_init
pthread_rwlock_wrlock
pthread_rwlock_unlock
And that works very fine as well