diff --git a/alib2std/src/alib/binomial_heap b/alib2std/src/alib/binomial_heap
new file mode 100644
index 0000000000000000000000000000000000000000..beaad7c7411a655004584339c7465297e6a6d9de
--- /dev/null
+++ b/alib2std/src/alib/binomial_heap
@@ -0,0 +1 @@
+#include <extensions/heaps/BinomialHeap.h>
diff --git a/alib2std/src/alib/cpp_heap b/alib2std/src/alib/cpp_heap
new file mode 100644
index 0000000000000000000000000000000000000000..bd542fa5d5a8b172df365c93199ed4e83f57a5c0
--- /dev/null
+++ b/alib2std/src/alib/cpp_heap
@@ -0,0 +1 @@
+#include <extensions/heaps/CppHeap.h>
diff --git a/alib2std/src/alib/fibonacci_heap b/alib2std/src/alib/fibonacci_heap
new file mode 100644
index 0000000000000000000000000000000000000000..08210d217a3849b3ff29a7e8483755d565fadf81
--- /dev/null
+++ b/alib2std/src/alib/fibonacci_heap
@@ -0,0 +1 @@
+#include <extensions/heaps/FibonacciHeap.h>
diff --git a/alib2std/src/extensions/heaps/BinomialHeap.h b/alib2std/src/extensions/heaps/BinomialHeap.h
new file mode 100644
index 0000000000000000000000000000000000000000..0f8ba284f32d87ef1759724b0b6e97f7f5a8246b
--- /dev/null
+++ b/alib2std/src/extensions/heaps/BinomialHeap.h
@@ -0,0 +1,230 @@
+/*
+ * BinomialHeap.h
+ *
+ *   Created on: Apr 7, 2016
+ *       Author: Jan Broz
+ */
+
+#ifndef BINOMIAL_HEAP_INCLUDED
+#define BINOMIAL_HEAP_INCLUDED
+
+#include <stdexcept>
+
+namespace alib {
+
+/// binomial heap used as mergeable priority queue
+template< typename elem_t >
+class BinomialHeap {
+public:
+
+	BinomialHeap( int (* compare)( const elem_t &, const elem_t & ) );
+
+	~BinomialHeap();
+
+	/// inserts a node with new value into the heap
+	void insert( const elem_t & value );
+
+	/// finds the maximum value in the heap
+	const elem_t & getMax() const {
+		return (*searchMax( const_cast<Node**>(&_head) ))->value;
+	}
+
+	/// finds and removes the maximum value from the heap
+	elem_t extractMax();
+
+	/// merges this heap with another heap (!! this is a DESTRUCTIVE merge, heap in argument will be cleared !!)
+	void mergeWith( BinomialHeap<elem_t> && that );
+
+	size_t size() const {
+		return _size;
+	}
+
+protected:
+
+	struct Node {
+		elem_t value;
+		unsigned   degree;
+		Node * parent;
+		Node * child;
+		Node * sibling;
+		Node( const elem_t & val, unsigned deg = 0, Node * par = NULL, Node * chld = NULL, Node * sib = NULL )
+		 : value(val), degree(deg), parent(par), child(chld), sibling(sib) {}
+	};
+
+	Node *  _head;    ///< head of a singly linked list of binomial trees
+	size_t    _size;    ///< count of elements stored in the heap
+	int (*  _compare)( const elem_t &, const elem_t & ); ///< user-defined comparator function
+
+protected:
+
+	/// deletes one linked list of binomial trees
+	void deleteTreeList( Node * head );
+
+	/// searches the linked list and returns address of variable pointing to the node with maximum value
+	Node * * searchMax( Node * * head ) const;
+	/// merges linked lists from 2 binomial heaps and returns address of head of the new linked list
+
+	Node *   mergeHeaps( Node * head1, Node * head2 );
+	/// merges 2 linked lists of binomial trees and sorts the trees by increasing degree
+
+	Node *   mergeListsByDeg( Node * head1, Node * head2 );
+	/// reverses a linked list
+
+	Node *   reverseList( Node * head );
+	/// links root of tree1 to root of tree2 (tree1 becomes child of tree2)
+	Node *   linkTreeToTree( Node * root1, Node * root2 );
+
+};
+
+
+template< typename elem_t >
+BinomialHeap<elem_t>::BinomialHeap( int (* compare)( const elem_t &, const elem_t & ) ) : _head( NULL ), _size( 0 ), _compare( compare ) {
+}
+
+template< typename elem_t >
+BinomialHeap<elem_t>::~BinomialHeap() {
+	deleteTreeList( _head );
+}
+
+template< typename elem_t >
+void BinomialHeap<elem_t>::deleteTreeList( Node * head ) {
+	while (head != NULL) {
+		Node * sibling = head->sibling;
+		deleteTreeList( head->child );
+		delete head;
+		head = sibling;
+	}
+}
+
+template< typename elem_t >
+void BinomialHeap<elem_t>::insert( const elem_t & value ) {
+	Node * newNode = new Node( value, 0, NULL, NULL, NULL );
+
+	_head = mergeHeaps( _head, newNode ); // merge the current heap with the newNode,
+	                              // as if the newNode was a single-element heap
+	_size++;
+}
+
+template< typename elem_t >
+elem_t BinomialHeap<elem_t>::extractMax() {
+	if ( _size == 0 )
+		throw std::out_of_range ( "Heap is empty." );
+
+	Node * * ptrToMax = searchMax( &_head );    // find the node with maximum value
+	Node * max = *ptrToMax;
+
+	*ptrToMax = max->sibling;       // disconnect it from the linked list
+
+	Node * chlHead = reverseList( max->child );       // merge them with the heap in reversed order
+	_head = mergeHeaps( this->_head, chlHead );
+
+	_size--;
+	elem_t maxVal = max->value;
+	delete max;                     // extract the value from node and return it
+	return maxVal;
+}
+
+template< typename elem_t >
+void BinomialHeap<elem_t>::mergeWith( BinomialHeap<elem_t> && that ) {
+	if (this->_compare != that._compare)    // nodes of these heaps are sorted by different condition
+		throw std::logic_error("compare functions aren't equal, unable to merge");
+
+	this->_head = mergeHeaps( this->_head, that._head );    // move the other heap into this heap
+	that._head = NULL;
+
+	this->_size += that._size;
+	that._size = 0;
+}
+
+template< typename elem_t >
+typename BinomialHeap<elem_t>::Node * * BinomialHeap<elem_t>::searchMax( Node * * head ) const {
+	Node * max = *head, * * ptrToMax = head;
+	for (Node * actual = * head, * prev = NULL; actual != NULL; prev = actual, actual = actual->sibling) {
+		if (_compare( actual->value, max->value ) > 0) {
+			max = actual;
+			ptrToMax = &prev->sibling;
+		}
+	}
+	return ptrToMax;
+}
+
+template< typename elem_t >
+typename BinomialHeap<elem_t>::Node * BinomialHeap<elem_t>::mergeHeaps( Node * head1, Node * head2 ) {
+	if ( ! head1 )
+		return head2;
+
+	if ( ! head2 )
+		return head1;
+
+	head1 = mergeListsByDeg( head1, head2 );   // first, merge the lists of trees by their degrees
+
+	Node * actual = head1;
+	Node * * toLink = & head1;
+	while (actual->sibling) {
+		Node * next = actual->sibling;
+
+		if (actual->degree != next->degree || (next->sibling && next->sibling->degree == actual->degree)) {
+			toLink = &actual->sibling;                // not merging trees with same degree
+			actual = next;                            // or postponing the merge by 1 iteration
+		} else if (_compare( actual->value, next->value ) >= 0) {
+			actual->sibling = next->sibling;          // merging 2 binomial trees with same degree
+			actual = linkTreeToTree( next, actual );  // 'next'    becomes child of   'actual'
+		} else {
+			*toLink = next;                           // merging 2 binomial trees with same degree
+			actual = linkTreeToTree( actual, next );  // 'actual'  becomes child of   'next'
+		}
+	}
+
+	return head1;
+}
+
+template< typename elem_t >
+typename BinomialHeap<elem_t>::Node * BinomialHeap<elem_t>::mergeListsByDeg( Node * head1, Node * head2 ) {
+	Node * newHead = NULL;
+	Node * * toLink = &newHead;
+	while (head1 && head2) {
+		if (head1->degree < head2->degree) {
+			*toLink = head1;                      // linking node from first list
+			toLink = &head1->sibling;             // and moving first pointer
+			head1 = head1->sibling;
+		} else {
+			*toLink = head2;                      // linking node from second list
+			toLink = &head2->sibling;             // and moving second pointer
+			head2 = head2->sibling;
+		}
+	}
+	if (!head1)
+		*toLink = head2;        // list1 ended, link the rest of list2
+	else
+		*toLink = head1;        // list2 ended, link the rest of list1
+
+	return newHead;
+}
+
+template< typename elem_t >
+typename BinomialHeap<elem_t>::Node * BinomialHeap<elem_t>::reverseList( Node * head ) {
+	Node * prev = NULL;
+
+	while (head) {
+		Node * next = head->sibling;
+		head->sibling = prev;
+		prev = head;
+		head = next;
+	}
+
+	return prev;
+}
+
+template< typename elem_t >
+typename BinomialHeap<elem_t>::Node * BinomialHeap<elem_t>::linkTreeToTree( Node * root1, Node * root2 ) {
+	root1->parent = root2;
+	root1->sibling = root2->child;
+	root2->child = root1;
+	root2->degree++;
+
+	return root2;
+}
+
+} /* namespace alib */
+
+#endif // BINOMIAL_HEAP_INCLUDED
diff --git a/alib2std/src/extensions/heaps/CppHeap.h b/alib2std/src/extensions/heaps/CppHeap.h
new file mode 100644
index 0000000000000000000000000000000000000000..eeebc4a6f49a43697f649081353848d39e1b0aff
--- /dev/null
+++ b/alib2std/src/extensions/heaps/CppHeap.h
@@ -0,0 +1,81 @@
+/*
+ * CppHeap.h
+ *
+ *   Created on: Jan 9, 2019
+ *       Author: Jan Travnicek
+ */
+
+#ifndef CPP_HEAP_INCLUDED
+#define CPP_HEAP_INCLUDED
+
+#include <algorithm>
+#include <vector>
+
+namespace alib {
+
+/// binomial heap used as mergeable priority queue
+template < typename elem_t >
+class CppHeap {
+public:
+	CppHeap( int (* compare)( const elem_t &, const elem_t & ) );
+
+	~CppHeap();
+
+	/// inserts a node with new value into the heap
+	void insert( const elem_t & value );
+
+	/// finds the maximum value in the heap
+	const elem_t & getMax() const {
+		return _data.front ( );
+	}
+
+	/// finds and removes the maximum value from the heap
+	elem_t extractMax();
+
+	/// merges this heap with another heap (!! this is a DESTRUCTIVE merge, heap in argument will be cleared !!)
+	void mergeWith( CppHeap<elem_t> && that );
+
+	size_t size() const {
+		return _data.size ( );
+	}
+
+protected:
+	int (* _compare)( const elem_t &, const elem_t & ); ///< user-defined comparator function
+	std::vector < elem_t > _data;
+};
+
+
+template< typename elem_t >
+CppHeap<elem_t>::CppHeap( int (* compare)( const elem_t &, const elem_t & ) ) : _compare( compare ) {
+}
+
+template< typename elem_t >
+CppHeap<elem_t>::~CppHeap() {
+}
+
+template< typename elem_t >
+void CppHeap<elem_t>::insert( const elem_t & value ) {
+	_data.push_back ( value );
+	std::push_heap ( _data.begin ( ), _data.end ( ), _compare );
+}
+
+template< typename elem_t >
+elem_t CppHeap<elem_t>::extractMax() {
+	if ( _data.size ( ) == 0 )
+		throw std::out_of_range ( "Heap is empty." );
+
+	elem_t res = _data.front ( );
+	std::pop_heap ( _data.begin ( ), _data.end ( ), _compare );
+	_data.pop_back ( );
+	return res;
+}
+
+template< typename elem_t >
+void CppHeap<elem_t>::mergeWith( CppHeap<elem_t> && that ) {
+	_data.insert ( _data.end ( ), that._data.begin ( ), that._data.end ( ) );
+	std::make_heap ( _data.begin ( ), _data.end ( ), _compare );
+}
+
+} /* namespace alib */
+
+#endif // CPP_HEAP_INCLUDED
diff --git a/alib2std/src/extensions/heaps/FibonacciHeap.h b/alib2std/src/extensions/heaps/FibonacciHeap.h
new file mode 100644
index 0000000000000000000000000000000000000000..ec22399f757a3f194ef3d23981918c4c455518ab
--- /dev/null
+++ b/alib2std/src/extensions/heaps/FibonacciHeap.h
@@ -0,0 +1,283 @@
+/*
+ * FibonacciHeap.h
+ *
+ *   Created on: Apr 7, 2016
+ *       Author: Jan Broz
+ */
+
+#ifndef FIBONACCI_HEAP_INCLUDED
+#define FIBONACCI_HEAP_INCLUDED
+
+#include <stdexcept>
+#include <cmath>      // maxDegree
+
+namespace alib {
+
+/// fibonacci heap used as mergeable priority queue
+template< typename elem_t >
+class FibonacciHeap {
+public:
+	FibonacciHeap( int (* compare)( const elem_t &, const elem_t & ) );
+
+	~FibonacciHeap();
+
+	/// inserts a node with new value into the heap
+	void insert( const elem_t & value );
+
+	/// finds the maximum value in the heap
+	const elem_t & getMax() const {
+		return _max->value;
+	}
+
+	/// finds and removes the maximum value from the heap
+	elem_t extractMax();
+
+	/// merges this heap with another heap (!! this is a DESTRUCTIVE merge, heap in argument will be cleared !!)
+	void mergeWith( FibonacciHeap<elem_t> && that );
+
+	size_t size() const {
+		return _size;
+	}
+
+//	void print ( );
+
+//	void checkConsystency ( );
+
+protected:
+	struct Node {
+		elem_t value;
+		unsigned degree;
+		bool   mark;
+		Node * parent;
+		Node * child;
+		Node * prev;
+		Node * next;
+		Node(const elem_t & val, unsigned deg = 0, Node * par = NULL, Node * chld = NULL, Node * pr = NULL, Node * ne = NULL)
+		 : value(val), degree(deg), mark(false), parent(par), child(chld), prev(pr), next(ne) {}
+	};
+
+	Node *  _max;     ///< pointer to cyclic doubly linked list of trees
+	size_t    _size;    ///< count of elements stored in the heap
+	int (*  _compare)( const elem_t &, const elem_t & ); ///< user-defined comparator function
+
+protected:
+
+	/// deletes one linked list of trees
+	void deleteTreeList( Node * head );
+
+	/// connects doubly linked lists from 2 fibonacci heaps and returns address of head of the new linked list
+	void mergeHeaps( Node * & max1, Node * & max2 );
+
+	/// goes through list of trees and merges trees with same degree
+	void consolidate();
+
+	/// links tree to child list of node
+	void linkTreeToNode( Node * node, Node * tree );
+
+//	void printNode ( Node * node );
+
+//	void checkConsystency ( Node * node, Node * parent );
+};
+
+
+template< typename elem_t >
+FibonacciHeap<elem_t>::FibonacciHeap ( int (* compare)( const elem_t &, const elem_t & ) ) : _max( NULL ), _size( 0 ), _compare( compare ) {
+}
+
+template< typename elem_t >
+FibonacciHeap<elem_t>::~FibonacciHeap ( ) {
+	deleteTreeList( _max );
+}
+
+template< typename elem_t >
+void FibonacciHeap<elem_t>::deleteTreeList( Node * head ) {
+	if ( ! head )
+		return;
+
+	Node * actual = head;
+	do {
+		Node * next = actual->next;
+		deleteTreeList( actual->child );
+		delete actual;
+		actual = next;
+	} while (actual != head);
+}
+
+template< typename elem_t >
+void FibonacciHeap<elem_t>::insert( const elem_t & value ) {
+	Node * newNode = new Node( value, 0, NULL, NULL, NULL, NULL );
+	newNode->prev = newNode;
+	newNode->next = newNode;     // make this node be a single-element cyclic list
+
+	if (!_max) {
+		_max = newNode;       // this heap is empty, newNode becomes head of a linked list
+		_size = 1;
+		return;
+	}
+
+	mergeHeaps( _max, newNode );    // link the newNode into the existing linked list
+
+	_max = _compare( _max->value, newNode->value ) > 0 ? _max : newNode;
+
+	_size++;
+}
+
+template< typename elem_t >
+elem_t FibonacciHeap<elem_t>::extractMax() {
+	if ( _max == NULL )
+		throw std::out_of_range ( "Heap is empty." );
+
+	Node * z = _max;
+	elem_t maxVal = z->value;
+
+	if (z->child != NULL) {
+		Node * z1 = z->child;
+		do {
+			z1->parent = NULL;
+			z1 = z1->next;
+		} while (z1 != z->child);
+	}
+
+	mergeHeaps ( z, z->child );
+
+	if (z == z->next)
+		_max = NULL;
+	else {
+		_max = z->next;
+		_max->prev = z->prev;
+		z->prev->next = _max;
+		consolidate();
+	}
+
+	_size--;
+	delete z;
+	return maxVal;
+}
+
+template< typename elem_t >
+void FibonacciHeap<elem_t>::mergeWith( FibonacciHeap<elem_t> && that ) {
+	if (this->_compare != that._compare)    // nodes of these heaps are sorted by different condition
+		throw std::logic_error("compare functions aren't equal, unable to merge");
+
+	mergeHeaps( this->_max, that._max );    // link the other heap into this heap
+	this->_max = _compare( _max->value, that._max->value ) > 0 ? this->_max : that._max;
+	that._max = NULL;
+
+	this->_size += that._size;
+	that._size = 0;
+}
+
+template< typename elem_t >
+void FibonacciHeap<elem_t>::mergeHeaps( Node * & max1, Node * & max2 ) {
+	if ( ! max1 ) {
+		max1 = max2;    // this heap is empty, move the content from the other heap inside
+	} else if ( max2 ) {
+		Node * max2prev = max2->prev;
+
+		max2->prev->next = max1;
+		max2->prev = max1->prev;    // this magicaly works even if the lists contain only one node
+		max1->prev->next = max2;
+		max1->prev = max2prev;
+	}
+}
+
+template< typename elem_t >
+void FibonacciHeap<elem_t>::consolidate() {
+	unsigned maxDegree = log2( _size );
+	Node * * rootsByDegree = new Node * [ maxDegree + 1 ];
+	for (unsigned i = 0; i <= maxDegree; i++)
+		rootsByDegree[i] = NULL;
+
+	Node * next = _max;
+	Node * actual = next;
+
+	bool finish = next == next->next;
+	while ( ! finish ) {
+		actual = next;
+		next = actual->next;
+		finish = next == rootsByDegree [ next->degree ];
+
+		while ( rootsByDegree[ actual->degree ] != NULL) {
+			Node * other = rootsByDegree[ actual->degree ];
+			rootsByDegree[ actual->degree ] = NULL;
+
+			if (_compare( actual->value, other->value ) > 0) {
+				linkTreeToNode( actual, other );
+			} else {
+				linkTreeToNode( other, actual );
+				actual = other;
+			}
+
+		}
+		rootsByDegree[ actual->degree ] = actual;
+	};
+
+	delete [] rootsByDegree;
+
+	_max = actual;
+	Node * node = actual;
+	do {
+		if (_compare( node->value, _max->value ) > 0)
+			_max = node;
+		node = node->next;
+	} while ( node != actual );
+}
+
+template< typename elem_t >
+void FibonacciHeap<elem_t>::linkTreeToNode( Node * node, Node * tree ) {
+	tree->prev->next = tree->next;
+	tree->next->prev = tree->prev;
+
+	tree->prev = tree;
+	tree->next = tree;
+
+	tree->parent = node;
+	node->degree ++;
+
+	mergeHeaps ( node->child, tree );
+}
+
+/*template < typename elem_t >
+void FibonacciHeap<elem_t>::print() {
+	if ( _max == NULL )
+		std::cout << "Empty" << std::endl;
+
+	printNode ( _max );
+}
+
+template < typename elem_t >
+void FibonacciHeap < elem_t >::printNode ( Node * node ) {
+	if ( node == NULL )
+		return;
+
+	Node * actual = node;
+	do {
+		std::cout << " Value: " << actual->value << " Parent: " << ((actual->parent) ? actual->parent->id : -1) << " Left: " << actual->prev->id << " Right: " << actual->next->id << std::endl;
+		printNode ( actual->child );
+		actual = actual->next;
+
+	} while ( node != actual );
+}
+
+template < typename elem_t >
+void FibonacciHeap<elem_t>::checkConsystency() {
+	checkConsystency ( _max, NULL );
+}
+
+template < typename elem_t >
+void FibonacciHeap < elem_t >::checkConsystency ( Node * node, Node * parent ) {
+	if ( node == NULL )
+		return;
+
+	Node * actual = node;
+	do {
+		assert ( node == node->prev->next && node->next->prev == node && node->parent == parent );
+		checkConsystency ( actual->child, actual );
+		actual = actual->next;
+
+	} while ( node != actual );
+}*/
+
+} /* namespace alib */
+
+#endif // FIBONACCI_HEAP_INCLUDED
diff --git a/alib2std/test-src/extensions/heaps/HeapsTest.cpp b/alib2std/test-src/extensions/heaps/HeapsTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..53a6df9164f28d817a63631fac6d690af85a874b
--- /dev/null
+++ b/alib2std/test-src/extensions/heaps/HeapsTest.cpp
@@ -0,0 +1,116 @@
+#include "HeapsTest.h"
+
+#include <alib/cpp_heap>
+#include <alib/binomial_heap>
+#include <alib/fibonacci_heap>
+
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( HeapsTest, "bits" );
+CPPUNIT_TEST_SUITE_REGISTRATION( HeapsTest );
+
+void HeapsTest::setUp() {
+}
+
+void HeapsTest::tearDown() {
+}
+
+int comparator ( const int & a, const int & b ) {
+	return ( b < a ) - ( a < b );
+}
+
+int less ( const int & a, const int & b ) {
+	return a < b;
+}
+
+void HeapsTest::testHeaps ( ) {
+	alib::BinomialHeap < int > bHeap ( comparator );
+	alib::CppHeap < int > cHeap ( less );
+	alib::FibonacciHeap < int > fHeap ( comparator );
+
+	auto size = [ & ] ( ) {
+		int b = bHeap.size ( );
+		int c = cHeap.size ( );
+		int f = fHeap.size ( );
+		CPPUNIT_ASSERT ( b == c && c == f );
+		return b;
+	};
+
+	auto push = [ & ] ( int a ) {
+		bHeap.insert ( a );
+		cHeap.insert ( a );
+		fHeap.insert ( a );
+	};
+
+	auto pop = [ & ] ( ) {
+		int b = bHeap.extractMax ( );
+		int c = cHeap.extractMax ( );
+		int f = fHeap.extractMax ( );
+		if ( b != c || c != f) {
+			std::cerr << "??" << std::endl << "size = " << size ( ) << std::endl;
+			std::cerr << "b = " << b << " c = " << c << " f = " << f << std::endl;
+		}
+		CPPUNIT_ASSERT ( b == c );
+		CPPUNIT_ASSERT ( c == f );
+		return b;
+	};
+
+	auto mergeRandom = [ & ] ( unsigned limit ) {
+		alib::BinomialHeap < int > rbHeap ( comparator );
+		alib::CppHeap < int > rcHeap ( comparator );
+		alib::FibonacciHeap < int > rfHeap ( comparator );
+
+		for ( unsigned i = 0; i < limit; ++ i ) {
+			unsigned val = rand ( ) % 1000;
+			rbHeap.insert ( val );
+			rcHeap.insert ( val );
+			rfHeap.insert ( val );
+		}
+
+		bHeap.mergeWith ( std::move ( rbHeap ) );
+		cHeap.mergeWith ( std::move ( rcHeap ) );
+		fHeap.mergeWith ( std::move ( rfHeap ) );
+	};
+
+	push ( 1 );
+	CPPUNIT_ASSERT ( size ( ) == 1 );
+	CPPUNIT_ASSERT ( pop ( ) == 1 );
+	std::cout << "merge random 50" << std::endl;
+	mergeRandom ( 50 );
+	CPPUNIT_ASSERT ( size ( ) == 50 );
+	std::cout << "pop 25" << std::endl;
+	for ( unsigned i = 0; i < 25; ++ i ) {
+		std::cout << "pop = " << pop ( ) << std::endl;
+	}
+	std::cout << "merge random 50" << std::endl;
+	mergeRandom ( 50 );
+	CPPUNIT_ASSERT ( size ( ) == 75 );
+	std::cout << "pop 25" << std::endl;
+	for ( unsigned i = 0; i < 25; ++ i ) {
+		std::cout << "pop = " << pop ( ) << std::endl;
+	}
+	std::cout << "merge random 50" << std::endl;
+	mergeRandom ( 50 );
+	CPPUNIT_ASSERT ( size ( ) == 100 );
+	std::cout << "pop 25" << std::endl;
+	for ( unsigned i = 0; i < 25; ++ i ) {
+		std::cout << "pop = " << pop ( ) << std::endl;
+	}
+	std::cout << "merge random 50" << std::endl;
+	mergeRandom ( 50 );
+	CPPUNIT_ASSERT ( size ( ) == 125 );
+	std::cout << "pop 25" << std::endl;
+	for ( unsigned i = 0; i < 25; ++ i ) {
+		std::cout << "pop = " << pop ( ) << std::endl;
+	}
+	std::cout << "merge random 50" << std::endl;
+	mergeRandom ( 50 );
+	CPPUNIT_ASSERT ( size ( ) == 150 );
+	std::cout << "push random 25" << std::endl;
+//	fHeap.checkConsystency ( );
+	for ( unsigned i = 0; i < 25; ++ i ) {
+		push ( rand ( ) % 1000 );
+	}
+	std::cout << "pop all" << std::endl;
+	for ( unsigned i = 0; i < 175; ++ i ) {
+		std::cout << "pop = " << pop ( ) << std::endl;
+	}
+}
diff --git a/alib2std/test-src/extensions/heaps/HeapsTest.h b/alib2std/test-src/extensions/heaps/HeapsTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..96a5efaed46582951de1be4ad02f110e94caba90
--- /dev/null
+++ b/alib2std/test-src/extensions/heaps/HeapsTest.h
@@ -0,0 +1,19 @@
+#ifndef HEAPS_TEST_H_
+#define HEAPS_TEST_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class HeapsTest : public CppUnit::TestFixture
+{
+  CPPUNIT_TEST_SUITE( HeapsTest );
+  CPPUNIT_TEST( testHeaps );
+  CPPUNIT_TEST_SUITE_END();
+
+public:
+  void setUp();
+  void tearDown();
+
+  void testHeaps();
+};
+
+#endif  // HEAPS_TEST_H_