diff --git a/pydatastructs/linear_data_structures/_backend/cpp/algorithms/algorithms.cpp b/pydatastructs/linear_data_structures/_backend/cpp/algorithms/algorithms.cpp index 75f43d0b3..09ce3fd65 100644 --- a/pydatastructs/linear_data_structures/_backend/cpp/algorithms/algorithms.cpp +++ b/pydatastructs/linear_data_structures/_backend/cpp/algorithms/algorithms.cpp @@ -1,9 +1,12 @@ #include #include "quick_sort.hpp" +#include "bubble_sort.hpp" static PyMethodDef algorithms_PyMethodDef[] = { {"quick_sort", (PyCFunction) quick_sort, METH_VARARGS | METH_KEYWORDS, ""}, + {"bubble_sort", (PyCFunction) bubble_sort, + METH_VARARGS | METH_KEYWORDS, ""}, {NULL, NULL, 0, NULL} /* Sentinel */ }; diff --git a/pydatastructs/linear_data_structures/_backend/cpp/algorithms/bubble_sort.hpp b/pydatastructs/linear_data_structures/_backend/cpp/algorithms/bubble_sort.hpp new file mode 100644 index 000000000..fc09af208 --- /dev/null +++ b/pydatastructs/linear_data_structures/_backend/cpp/algorithms/bubble_sort.hpp @@ -0,0 +1,68 @@ +#ifndef LINEAR_DATA_STRUCTURES_ALGORITHMS_BUBBLE_SORT_HPP +#define LINEAR_DATA_STRUCTURES_ALGORITHMS_BUBBLE_SORT_HPP + +#define PY_SSIZE_T_CLEAN +#include +#include "../arrays/OneDimensionalArray.hpp" +#include "../arrays/DynamicOneDimensionalArray.hpp" +#include "../../../../utils/_backend/cpp/utils.hpp" + +static PyObject* bubble_sort_impl(PyObject* array, size_t lower, size_t upper, + PyObject* comp, size_t arr_length) { + for (size_t i = 0; i < arr_length - 1; i++) { + for (size_t j = lower; j < upper; j++) { + PyObject* j_PyObject = PyLong_FromSize_t(j); + PyObject* j1_PyObject = PyLong_FromSize_t(j+1); + if( _comp(PyObject_GetItem(array, j_PyObject), + PyObject_GetItem(array, j1_PyObject), comp) != 1 ) { + PyObject* tmp = PyObject_GetItem(array, j1_PyObject); + PyObject_SetItem(array, j1_PyObject, + PyObject_GetItem(array, j_PyObject)); + PyObject_SetItem(array, j_PyObject, tmp); + } + } + } + return array; +} + + +static PyObject* bubble_sort(PyObject* self, PyObject* args, PyObject* kwds) { + PyObject *args0 = NULL, *start = NULL, *end = NULL; + PyObject *comp = NULL, *pick_pivot_element = NULL; + size_t lower, upper, arr_length; + args0 = PyObject_GetItem(args, PyZero); + int is_DynamicOneDimensionalArray = _check_type(args0, &DynamicOneDimensionalArrayType); + int is_OneDimensionalArray = _check_type(args0, &OneDimensionalArrayType); + if( !is_DynamicOneDimensionalArray && !is_OneDimensionalArray ) { + raise_exception_if_not_array(args0); + return NULL; + } + comp = PyObject_GetItem(kwds, PyUnicode_FromString("comp")); + if( comp == NULL ) { + PyErr_Clear(); + } + start = PyObject_GetItem(kwds, PyUnicode_FromString("start")); + if( start == NULL ) { + PyErr_Clear(); + lower = 0; + } else { + lower = PyLong_AsSize_t(start); + } + end = PyObject_GetItem(kwds, PyUnicode_FromString("end")); + if( end == NULL ) { + PyErr_Clear(); + upper = PyObject_Length(args0) - 1; + } else { + upper = PyLong_AsSize_t(end); + } + arr_length = PyObject_Length(args0); + + args0 = bubble_sort_impl(args0, lower, upper, comp, arr_length); + if( is_DynamicOneDimensionalArray ) { + PyObject_CallMethod(args0, "_modify", "O", Py_True); + } + Py_INCREF(args0); + return args0; +} + +#endif diff --git a/pydatastructs/linear_data_structures/algorithms.py b/pydatastructs/linear_data_structures/algorithms.py index 0a0763421..bcc9da592 100644 --- a/pydatastructs/linear_data_structures/algorithms.py +++ b/pydatastructs/linear_data_structures/algorithms.py @@ -1361,8 +1361,9 @@ def bubble_sort(array, **kwargs): .. [1] https://en.wikipedia.org/wiki/Bubble_sort """ - raise_if_backend_is_not_python( - bubble_sort, kwargs.get('backend', Backend.PYTHON)) + backend = kwargs.pop("backend", Backend.PYTHON) + if backend == Backend.CPP: + return _algorithms.bubble_sort(array, **kwargs) start = kwargs.get('start', 0) end = kwargs.get('end', len(array) - 1) comp = kwargs.get("comp", lambda u, v: u <= v) diff --git a/pydatastructs/linear_data_structures/tests/benchmarks/test_algorithms.py b/pydatastructs/linear_data_structures/tests/benchmarks/test_algorithms.py index 408b68fbe..4c112aeca 100644 --- a/pydatastructs/linear_data_structures/tests/benchmarks/test_algorithms.py +++ b/pydatastructs/linear_data_structures/tests/benchmarks/test_algorithms.py @@ -1,6 +1,6 @@ import random, timeit, functools, os, pytest from pydatastructs import (OneDimensionalArray, Backend, - DynamicOneDimensionalArray, quick_sort) + DynamicOneDimensionalArray, quick_sort, bubble_sort) def _test_common_sort(sort, **kwargs): cpp = Backend.CPP @@ -34,3 +34,8 @@ def _common(array_type, dtype, *args, **kwargs): @pytest.mark.xfail def test_quick_sort(): _test_common_sort(quick_sort, size=4000) + + +@pytest.mark.xfail +def test_bubble_sort(): + _test_common_sort(bubble_sort, size=2000) diff --git a/pydatastructs/linear_data_structures/tests/test_algorithms.py b/pydatastructs/linear_data_structures/tests/test_algorithms.py index dde284e80..ba925866c 100644 --- a/pydatastructs/linear_data_structures/tests/test_algorithms.py +++ b/pydatastructs/linear_data_structures/tests/test_algorithms.py @@ -117,6 +117,7 @@ def test_quick_sort(): def test_bubble_sort(): _test_common_sort(bubble_sort) + _test_common_sort(bubble_sort, backend=Backend.CPP) def test_selection_sort(): _test_common_sort(selection_sort)