diff --git a/src/algorithms/sorting/quick-sort/QuickSortInPlace.js b/src/algorithms/sorting/quick-sort/QuickSortInPlace.js
index cc1f5e5068..b4b559f27e 100644
--- a/src/algorithms/sorting/quick-sort/QuickSortInPlace.js
+++ b/src/algorithms/sorting/quick-sort/QuickSortInPlace.js
@@ -4,7 +4,9 @@ export default class QuickSortInPlace extends Sort {
   /** Sorting in place avoids unnecessary use of additional memory, but modifies input array.
    *
    * This process is difficult to describe, but much clearer with a visualization:
-   * @see: http://www.algomation.com/algorithm/quick-sort-visualization
+   @see: https://www.hackerearth.com/practice/algorithms/sorting/quick-sort/visualize/
+   * put the array size and the elements and on click of the button the visualization appears
+   * here is the youtube video @see: https://www.youtube.com/watch?v=aXXWXz5rF64&ab_channel=udiprod
    *
    * @param {*[]} originalArray - Not sorted array.
    * @param {number} inputLowIndex
diff --git a/src/algorithms/sorting/tim-sort/README.md b/src/algorithms/sorting/tim-sort/README.md
new file mode 100644
index 0000000000..7047fa889e
--- /dev/null
+++ b/src/algorithms/sorting/tim-sort/README.md
@@ -0,0 +1,37 @@
+# Timsort
+
+
+Timsort is a sorting algorithm based on insertion sort and merge sort.
+it was invented by Peter Tim in 2002 and this sort is used in the
+Java's Array.sort() method as well as Python language's sorted() and sort() method,
+in this algorithm first we make the chunks of the array and sort
+them using Insertion Sort and then we merge those sorted chunks using
+merge of Merge Sort.
+
+The steps are:
+
+1. We divide the array into the blocks of Run
+2. Those divided blocks are then sorted using the insertion
+sort one by one
+3. Once these are sorted we merge the sorted array chunks and combine
+them using the merge sort.
+
+The size of the run can be 32 or 64 based on the array size, if those are power of two that
+will help us in the performance in the insertion sort
+
+Animated visualization of the timesort algorithm.
+
+![TimSort](https://www.youtube.com/watch?v=NVIjHj-lrT4)
+
+## Complexity
+
+| Name                  | Best            | Average             | Worst               | Memory    | Stable    | Comments  |
+| --------------------- | :-------------: | :-----------------: | :-----------------: | :-------: | :-------: | :-------- |
+| **Tim sort**        | n O(n)   | n n*log(n)       | n  n*log(n)       | log(n)    | Yes        |  Timsort requires space of O(n) |
+
+## References
+
+- [Wikipedia](https://en.wikipedia.org/wiki/Timsort)
+- [YouTube] [Part1](https://www.youtube.com/watch?v=emeME__917E)
+            [Part2](https://www.youtube.com/watch?v=6DOhQyqAAvU)
+            [Part3](https://www.youtube.com/watch?v=Yk4CBisILaw)
diff --git a/src/algorithms/sorting/tim-sort/TimSort.js b/src/algorithms/sorting/tim-sort/TimSort.js
new file mode 100644
index 0000000000..f68215deb3
--- /dev/null
+++ b/src/algorithms/sorting/tim-sort/TimSort.js
@@ -0,0 +1,133 @@
+import Sort from '../Sort';
+// import InsertionSort from '../insertion-sort/InsertionSort';
+
+export default class TimSort extends Sort {
+  /**
+  * @name sort
+  * @description performs sorting using TimSort algorithm
+  * @param {*[]} originalArray
+  * @return {*[]}
+  */
+
+  sort(originalArray) {
+    const RUN = 32;
+    // clone the array so that original is intact
+    // eslint-disable-next-line prefer-const
+    let array = [...originalArray];
+
+    // const lengthOfArray = array.length;
+
+    // if array has only one or zero element it is already sorted
+    if (array.length <= 1) {
+      return array;
+    }
+
+    // perform insertion sort on the array first
+    for (let index = 0; index < array.length; index += RUN) {
+      // this.array=new this.insertionSort().
+      this.array = this.insertionSort(
+        array,
+        index,
+        this.minValue(index + RUN - 1, array.length - 1),
+      );
+    }
+
+    // now merge the sorted chunks
+    for (let size = RUN; size < array.length; size *= 2) {
+      for (let left = 0; left < array.length; left += 2 * size) {
+        const mid = left + size - 1;
+        const right = this.minValue(left + 2 * size - 1, array.length - 1);
+
+        if (this.comparator.lessThan(mid, right)) {
+          this.merge(this.array, left, mid, right);
+        }
+      }
+    }
+
+    return this.array;
+  }
+
+  /**
+   * @description returns a minimum value
+   * @param {*} a
+   * @param {*} b
+   * @returns {*} minimum value of the two
+   */
+  minValue(a, b) {
+    return this.comparator.lessThan(a, b) ? a : b;
+  }
+
+  /**
+   * @description merge the sorted array (chunks of array)
+   * @param {*[]} array
+   * @param {*} left
+   * @param {*} mid
+   * @param {*} right
+   */
+  merge(array, left, mid, right) {
+    const localArray = [...array];
+    const leftLength = mid - left + 1;
+    const rightLength = right - mid;
+    const leftArray = [];
+    const rightArray = [];
+    for (let index = 0; index < leftLength; index += 1) {
+      leftArray[index] = array[left + index];
+    }
+
+    for (let index = 0; index < rightLength; index += 1) {
+      rightArray[index] = array[mid + 1 + index];
+    }
+
+    let i = 0;
+    let j = 0;
+    let k = left;
+
+    while (this.comparator.lessThan(i, leftLength) && this.comparator.lessThan(j, rightLength)) {
+      if (this.comparator.lessThanOrEqual(leftArray[i], rightArray[j])) {
+        localArray[k] = leftArray[i];
+        i += 1;
+      } else {
+        localArray[k] = rightArray[j];
+      }
+    }
+    while (this.comparator.lessThan(i, leftLength)) {
+      localArray[k] = rightArray[i];
+      k += 1;
+      i += 1;
+    }
+    while (this.comparator.lessThan(j, rightLength)) {
+      localArray[k] = rightArray[j];
+      k += 1;
+      j += 1;
+    }
+    // eslint-disable-next-line no-param-reassign
+    array = Array.from(localArray);
+  }
+
+  /**
+   * @description perform the insertion sort on the array chunks
+   * @param {*[]} array
+   * @param {*} left
+   * @param {*} right
+   * @returns {*[]}
+   */
+  insertionSort(array, left, right) {
+    const localArray = [...array];
+
+    for (let index = left + 1; index <= right; index += 1) {
+      const element = localArray[index];
+      this.callbacks.visitingCallback(element);
+      let j = index - 1;
+      while (this.comparator.greaterThanOrEqual(j, left)
+        && this.comparator.greaterThan(localArray[j], element)) {
+        localArray[j + 1] = localArray[j];
+        j -= 1;
+        if (j < 0) break;
+      }
+      localArray[j + 1] = element;
+    }
+    // eslint-disable-next-line no-param-reassign
+    array = localArray;
+    return array;
+  }
+}
diff --git a/src/algorithms/sorting/tim-sort/__test__/TimSort.test.js b/src/algorithms/sorting/tim-sort/__test__/TimSort.test.js
new file mode 100644
index 0000000000..98eb377f08
--- /dev/null
+++ b/src/algorithms/sorting/tim-sort/__test__/TimSort.test.js
@@ -0,0 +1,64 @@
+import TimSort from '../TimSort';
+import {
+  equalArr,
+  notSortedArr,
+  reverseArr,
+  sortedArr,
+  SortTester,
+} from '../../SortTester';
+
+// Complexity constants.
+const SORTED_ARRAY_VISITING_COUNT = 19;
+const NOT_SORTED_ARRAY_VISITING_COUNT = 19;
+const REVERSE_SORTED_ARRAY_VISITING_COUNT = 19;
+const EQUAL_ARRAY_VISITING_COUNT = 19;
+
+describe('TimSort', () => {
+  it('should sort array', () => {
+    SortTester.testSort(TimSort);
+  });
+
+  it('should sort array with custom comparator', () => {
+    SortTester.testSortWithCustomComparator(TimSort);
+  });
+
+  it('should do stable sorting', () => {
+    SortTester.testSortStability(TimSort);
+  });
+
+  it('should sort negative numbers', () => {
+    SortTester.testNegativeNumbersSort(TimSort);
+  });
+
+  it('should visit EQUAL array element specified number of times', () => {
+    SortTester.testAlgorithmTimeComplexity(
+      TimSort,
+      equalArr,
+      EQUAL_ARRAY_VISITING_COUNT,
+    );
+  });
+
+  it('should visit SORTED array element specified number of times', () => {
+    SortTester.testAlgorithmTimeComplexity(
+      TimSort,
+      sortedArr,
+      SORTED_ARRAY_VISITING_COUNT,
+    );
+  });
+
+  it('should visit NOT SORTED array element specified number of times', () => {
+    SortTester.testAlgorithmTimeComplexity(
+      TimSort,
+      notSortedArr,
+      NOT_SORTED_ARRAY_VISITING_COUNT,
+    );
+  });
+
+  it('should visit REVERSE SORTED array element specified number of times', () => {
+    SortTester.testAlgorithmTimeComplexity(
+      TimSort,
+      reverseArr,
+      REVERSE_SORTED_ARRAY_VISITING_COUNT,
+    );
+  });
+});