diff --git a/doc/algorithm.qbk b/doc/algorithm.qbk
index becad4629..6217cb4f8 100644
--- a/doc/algorithm.qbk
+++ b/doc/algorithm.qbk
@@ -68,6 +68,7 @@ Thanks to all the people who have reviewed this library and made suggestions for
 [include hex.qbk]
 [include is_palindrome.qbk]
 [include is_partitioned_until.qbk]
+[include shuffle_weighted.qbk]
 [endsect]
 
 
diff --git a/doc/shuffle_weighted.qbk b/doc/shuffle_weighted.qbk
new file mode 100644
index 000000000..4c68feebd
--- /dev/null
+++ b/doc/shuffle_weighted.qbk
@@ -0,0 +1,84 @@
+[/ File shuffle_weighted.qbk]
+
+[section:shuffle_weighted shuffle_weighted]
+
+[/license
+Copyright (c) 2017 Alexander Zaitsev
+
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+]
+
+The header file 'shuffle_weighted.hpp' contains shuffle_weighted algorithm. There is range-based version.
+The algorithms rearrange the elements randomly with weights, using random number generator.
+
+The routine `shuffle_weighted` takes a item sequence and a weight sequences.
+
+The routines come in 2 forms; the first one takes two iterators to define the item range, one iterator to define the beginning of weight range and random generator. The second form takes range to define the item sequence, range to define weight sequence and random generator.
+
+
+[heading interface]
+
+There are two versions of algorithms:
+1) takes four iterators and random generator.
+2) takes two ranges and random generator.
+
+Also there are two versions for old compilers (which doesn't support C++11 or higher standard).
+Difference is only one: C++11 or higher version takes UniformRandomBitGenerator parameter as universal reference, version for old compiler takes UniformRandomBitGenerator as reference.
+
+For C++11 or higher compilers:
+``
+template<typename ForwardIterator1, typename ForwardIterator2, typename UniformRandomBitGenerator>
+void shuffle_weighted(ForwardIterator1 item_begin, ForwardIterator1 item_end, ForwardIterator2 weight_begin, ForwardIterator2 weight_end, UniformRandomBitGenerator&& g);
+template<typename Range1, typename Range2, typename UniformRandomBitGenerator>
+void shuffle_weighted(Range1& item_range, Range2& weight_range, UniformRandomBitGenerator&& g);
+``
+
+For old compilers:
+``
+template<typename ForwardIterator1, typename ForwardIterator2, typename UniformRandomBitGenerator>
+void shuffle_weighted(ForwardIterator1 item_begin, ForwardIterator1 item_end, ForwardIterator2 weight_begin, ForwardIterator2 weight_end, UniformRandomBitGenerator& g);
+template<typename Range1, typename Range2, typename UniformRandomBitGenerator>
+void shuffle_weighted(Range1& item_range, Range2& weight_range, UniformRandomBitGenerator& g);
+``
+
+[heading Examples]
+
+Given the containers:
+std::vector<int> emp_vec, emp_order,
+std::vector<int> one{1}, one_order{1},
+std::vector<int> two{1, 2}, two_order{1, 2}, then
+``
+
+shuffle_weighted(emp_vec, emp_order))  --> no changes
+shuffle_weighted(one, one_order))  --> no changes
+shuffle_weighted(two, two_order))  --> weighted-random result
+``
+
+[heading Iterator Requirements]
+
+`shuffle_weighted` works on Forawrd-compatible iterators (for item and weight sequences both).
+
+[heading Complexity]
+
+All of the variants of `shuffle_weighted` runs in ['O(N^2)] time.
+
+[heading Exception Safety]
+
+All of the variants of `shuffle_weighted` takes their parameters by iterators or reference, and do not depend upon any global state. Therefore, all the routines in this file provide the strong exception guarantee.
+
+[heading Notes]
+* Weights should be bigger than 0.
+
+* If ItemSequence and WeightSequence sizes are different, behavior is undefined.
+
+* `shuffle_weighted` works also on empty sequences.
+
+* Be careful: weights can be changed inside the function.
+[endsect]
+
+[/ File shuffle_weighted.qbk
+Copyright 2017 Alexander Zaitsev
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
+]
diff --git a/example/Jamfile.v2 b/example/Jamfile.v2
index 4512a53bb..16f4e4179 100644
--- a/example/Jamfile.v2
+++ b/example/Jamfile.v2
@@ -22,4 +22,4 @@ exe clamp_example   : clamp_example.cpp ;
 exe search_example  : search_example.cpp ;
 exe is_palindrome_example  : is_palindrome_example.cpp;
 exe is_partitioned_until_example  : is_partitioned_until_example.cpp;
-
+exe shuffle_weighted_example  : shuffle_weighted_example.cpp;
diff --git a/example/shuffle_weighted_example.cpp b/example/shuffle_weighted_example.cpp
new file mode 100644
index 000000000..3f1360999
--- /dev/null
+++ b/example/shuffle_weighted_example.cpp
@@ -0,0 +1,50 @@
+/*
+  Copyright (c) Alexander Zaitsev <zamazan4ik@gmail.com>, 2017
+
+  Distributed under the Boost Software License, Version 1.0. (See
+  accompanying file LICENSE_1_0.txt or copy at
+  http://www.boost.org/LICENSE_1_0.txt)
+
+  See http://www.boost.org/ for latest version.
+*/
+
+#include <vector>
+#include <iostream>
+#include <random>
+
+#include <boost/algorithm/shuffle_weighted.hpp>
+
+
+namespace ba = boost::algorithm;
+
+int main ( int /*argc*/, char * /*argv*/ [] )
+{
+    // WARNING: Example require C++11 or newer compiler
+    std::random_device rd;
+    std::mt19937 g(rd());
+    {
+        std::cout << "shuffle_weighted with iterators:\n";
+        std::vector<int> vec{1, 2, 3, 4, 5}, order{4, 2, 3, 1, 0};
+
+        ba::shuffle_weighted(vec.begin(), vec.end(), order.begin(), order.end(), g);
+        for (const auto& x : vec)
+        {
+            std::cout << x << ", ";
+        }
+        std::cout << std::endl;
+    }
+    {
+        std::cout << "shuffle_weighted with ranges:\n";
+        std::vector<int> vec{1, 2, 3, 4, 5}, order{4, 2, 3, 1, 0};
+
+        ba::shuffle_weighted(vec, order, g);
+        for (const auto& x : vec)
+        {
+            std::cout << x << ", ";
+        }
+        std::cout << std::endl;
+    }
+
+    return 0;
+}
+
diff --git a/include/boost/algorithm/shuffle_weighted.hpp b/include/boost/algorithm/shuffle_weighted.hpp
new file mode 100644
index 000000000..1a2ae67c3
--- /dev/null
+++ b/include/boost/algorithm/shuffle_weighted.hpp
@@ -0,0 +1,120 @@
+/*
+  Copyright (c) Alexander Zaitsev <zamazan4ik@gmail.com>, 2017
+
+  Distributed under the Boost Software License, Version 1.0. (See
+  accompanying file LICENSE_1_0.txt or copy at
+  http://www.boost.org/LICENSE_1_0.txt)
+
+  See http://www.boost.org/ for latest version.
+  
+*/
+
+/// \file  shuffle_weighted.hpp
+/// \brief Weighted shuffle.
+/// \author Alexander Zaitsev
+
+#ifndef BOOST_ALGORITHM_SHUFFLE_WEIGHTED_HPP
+#define BOOST_ALGORITHM_SHUFFLE_WEIGHTED_HPP
+
+#include <algorithm>
+
+#include <boost/config.hpp>
+
+#include <boost/algorithm/apply_permutation.hpp>
+
+#include <boost/random/uniform_int_distribution.hpp>
+#include <boost/random/uniform_real_distribution.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/conditional.hpp>
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+
+namespace boost { namespace algorithm {
+
+/// \fn shuffle_weighted (RandomAccessIterator1 item_begin, RandomAccessIterator1 item_end, RandomAccessIterator2 weight_begin, UniformRandomBitGenerator&& g)
+/// \brief Rearranges the elements in the range [item_begin,item_end) randomly with weights from weight_begin range, using g as uniform random number generator.
+///
+/// \param item_begin    The start of the item sequence
+/// \param item_end		 One past the end of the item sequence
+/// \param weight_begin  The start of the weight sequence.
+/// \param g             Uniform random number generator
+///
+/// \note Weight sequence size should be equal to item size. Otherwise behavior is undefined.
+///       Complexity: O(N^2).
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+template <typename ForwardIterator1, typename ForwardIterator2, typename UniformRandomBitGenerator>
+void shuffle_weighted(ForwardIterator1 item_begin, ForwardIterator1 item_end, 
+                      ForwardIterator2 weight_begin, ForwardIterator2 weight_end,
+					  UniformRandomBitGenerator&& g)
+#else
+template <typename ForwardIterator1, typename ForwardIterator2, typename UniformRandomBitGenerator>
+void shuffle_weighted(ForwardIterator1 item_begin, ForwardIterator1 item_end, 
+                      ForwardIterator2 weight_begin, ForwardIterator2 weight_end,
+					  UniformRandomBitGenerator& g)
+#endif
+{
+    typedef typename std::iterator_traits<ForwardIterator2>::value_type weight_t;
+    
+    weight_t total_weight = 0;
+    ForwardIterator2 weight_iter = weight_begin;
+    for(ForwardIterator1 it = item_begin; it != item_end; 
+        it++, weight_iter++)
+    {
+        total_weight += *weight_iter;
+    }
+
+    typedef typename boost::conditional<
+        boost::is_integral<weight_t>::value,
+        boost::random::uniform_int_distribution<weight_t>,
+        boost::random::uniform_real_distribution<weight_t>
+    >::type uniform_distr_t;
+    typedef typename uniform_distr_t::param_type param_type;
+
+    uniform_distr_t distribution;
+    for (; item_begin != item_end; 
+         item_begin++, weight_begin++) 
+    {
+        weight_t current_weights_sum = 0;
+        const weight_t random_value = distribution(g, param_type(0, total_weight));
+
+        ForwardIterator2 weight_iter = weight_begin;
+        for (ForwardIterator1 it = item_begin; it != item_end; 
+             it++, weight_iter++)
+        {
+            const weight_t weight = *weight_iter;
+            current_weights_sum += weight;
+            if (current_weights_sum >= random_value)
+            {
+                std::iter_swap(item_begin, it);
+                std::iter_swap(weight_begin, weight_iter);
+                total_weight -= weight;
+                break;
+            }
+        }
+    }
+}
+
+
+/// \fn shuffle_weighted (Range1& item_range, Range2& weight_range, UniformRandomBitGenerator&& g )
+/// \brief Rearranges the elements in the range [item_begin,item_end) randomly with weights from weight_begin range, using g as uniform random number generator.
+///
+/// \param item_range    The item sequence
+/// \param weight_range  The weight sequence
+/// \param g             Uniform random number generator
+///
+/// \note Weight sequence size should be equal to item size. Otherwise behavior is undefined.
+///       Complexity: O(N^2).
+template <typename Range1, typename Range2, typename UniformRandomBitGenerator>
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+void shuffle_weighted(Range1& item_range, Range2& weight_range, UniformRandomBitGenerator&& g)
+{
+    shuffle_weighted(boost::begin(item_range), boost::end(item_range), boost::begin(weight_range), boost::end(weight_range), static_cast<UniformRandomBitGenerator&&>(g));
+}
+#else
+void shuffle_weighted(Range1& item_range, Range2& weight_range, UniformRandomBitGenerator& g)
+{
+    shuffle_weighted(boost::begin(item_range), boost::end(item_range), boost::begin(weight_range), boost::end(weight_range), g);
+}
+#endif
+}}
+#endif //BOOST_ALGORITHM_SHUFFLE_WEIGHTED_HPP
diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
index fad1578fa..f40c85d15 100644
--- a/test/Jamfile.v2
+++ b/test/Jamfile.v2
@@ -73,6 +73,9 @@ alias unit_test_framework
      
 # Is_partitioned_until tests
      [ run is_partitioned_until_test.cpp unit_test_framework    : : : : is_partitioned_until_test ]
+     
+# Shuffle_weighted tests
+     [ run shuffle_weighted.cpp unit_test_framework    : : : : shuffle_weighted_test ]   
    ;
 }
 
diff --git a/test/shuffle_weighted_test.cpp b/test/shuffle_weighted_test.cpp
new file mode 100644
index 000000000..e6146fcfe
--- /dev/null
+++ b/test/shuffle_weighted_test.cpp
@@ -0,0 +1,79 @@
+/*
+  Copyright (c) Alexander Zaitsev <zamazan4ik@gmail.com>, 2017
+
+  Distributed under the Boost Software License, Version 1.0. (See
+  accompanying file LICENSE_1_0.txt or copy at
+  http://www.boost.org/LICENSE_1_0.txt)
+
+  See http://www.boost.org/ for latest version.
+*/
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MAIN
+
+#include <vector>
+
+#include <boost/algorithm/shuffle_weighted.hpp>
+
+#include <boost/random/mersenne_twister.hpp>
+#include <boost/test/unit_test.hpp>
+
+namespace ba = boost::algorithm;
+namespace br = boost::random;
+
+void test_shuffle_weighted()
+{
+    {
+        // Empty case
+        
+        br::mt19937_64 d;
+        std::vector<int> vec, weights;
+        
+        ba::shuffle_weighted(vec, weights, d);
+        BOOST_CHECK(vec.empty () && weights.empty());
+    }
+    {
+        // One element case
+        
+        br::mt19937_64 d;
+        std::vector<int> vec, weights;
+        vec.push_back(1);
+        weights.push_back(1);
+        std::vector<int> new_vec = vec, new_weights = weights;
+        
+        ba::shuffle_weighted(new_vec, new_weights, d);
+        BOOST_CHECK(vec == new_vec && weights == new_weights);
+    }
+    {
+        // Two element case
+        
+        br::mt19937_64 d;
+        std::vector<int> vec, rev_vec, weights;
+        vec.push_back(1); vec.push_back(2);
+        rev_vec.push_back(2); rev_vec.push_back(1);
+        weights = vec;
+        std::vector<int> new_vec = vec, new_weights = weights;
+        
+        ba::shuffle_weighted(new_vec, new_weights, d);
+        BOOST_CHECK(vec == new_vec || rev_vec == new_vec);
+    }
+    {
+        // Two element case, iterator interface
+        
+        br::mt19937_64 d;
+        std::vector<int> vec, rev_vec, weights;
+        vec.push_back(1); vec.push_back(2);
+        rev_vec.push_back(2); rev_vec.push_back(1);
+        weights = vec;
+        std::vector<int> new_vec = vec, new_weights = weights;
+        
+        ba::shuffle_weighted(new_vec.begin(), new_vec.end(), new_weights.begin(), new_weights.end(), d);
+        BOOST_CHECK(vec == new_vec || rev_vec == new_vec);
+    }
+}
+
+
+BOOST_AUTO_TEST_CASE(test_main)
+{
+    test_shuffle_weighted();
+}