490 likes | 1.15k Views
Internal Sorting. Objectives. Bubble Sort (reviewed ) Insertion Sort (reviewed ) Merge Sort Quick Sort Heap Sort Radix Sort Bucket Sort, Selection Sort, Shell Sort, BST and many others Efficiency. Bubble Sort. void bubbleSort (Array S, length n) { boolean isSorted = false;
E N D
Objectives • Bubble Sort (reviewed ) • Insertion Sort (reviewed ) • Merge Sort • Quick Sort • Heap Sort • Radix Sort • Bucket Sort, Selection Sort, Shell Sort, BST and many others • Efficiency
Bubble Sort void bubbleSort (Array S, length n) { boolean isSorted = false; while(!isSorted) { isSorted = true; for(i = 0; i<n; i++) { if(S[i] > S[i+1]) { int aux = S[i]; S[i] = S[i+1]; S[i+1] = aux; isSorted = false; } } }
Bubble Sort • 1 23 2 56 9 8 10 100 • 1 2 23 56 9 8 10 100 • 1 2 23 9 56 8 10 100 • 1 2 23 9 8 56 10 100 • 1 2 23 9 8 10 56 100 ---- finish the first traversal ---- ---- start again ---- • 1 2 23 9 8 10 56 100 • 1 2 9 23 8 10 56 100 • 1 2 9 8 23 10 56 100 • 1 2 9 8 10 23 56 100 ---- finish the second traversal ---- ---- start again ---- …………………. Why Bubble Sort ?
Insertion Sort void insert(const Element e, Element* list, int i) // Insert element e with key e.key into the ordered sequence list[0], …, list[i] such that the // resulting sequence is also ordered. Assume that e.key ≥ list[0].key. The array list must // have space allocated for at least i + 2 elements { while (i > 0 && e.getKey() < list[i].getKey()) { list[i+1] = list[i]; i--; } list[i+1] = e; }
void InsertSort(Element* list, constint n) // Sort list in nondecreasing order of key { list[0].setKey(MININT); for (int j = 2; j <= n; j++) insert(list[j], list, j-1); } Insertion Sort
26 5 77 1 61 11 59 15 48 19 5 26 1 77 11 61 15 59 19 48 1 5 26 77 11 15 59 61 19 48 1 5 11 15 26 59 61 77 19 48 1 5 11 15 19 26 48 59 61 77 Merge Sort – non recursive (familiar?)
26 5 77 1 61 11 59 15 48 19 5 26 11 59 19 48 5 26 77 11 15 59 19 48 1 61 1 5 26 61 77 11 15 19 48 59 1 5 11 15 19 26 48 59 61 77 Merge Sort – recursive
Merge Sort - recursive List mergesort(List inlist) { if (inlist.length() <= 1)return inlist; List l1 = half of the items from inlist; List l2 = other half of items from inlist; return merge(mergesort(l1), mergesort(l2)); }
1) Select: pick an element 2) Divide: rearrange elements so that x goes to its final position E 3) Recurse and Conquer: recursively sort Quick Sort
Quick Sort void QuickSort(Element* list, constint left, constint right) // Sort records list[left], …, list[right] into nondecreasing order on field key. Key pivot = list[left].key is // arbitrarily chosen as the pivot key. Pointers I and j are used to partition the sublist so that at any time // list[m].key pivot, m < I, and list[m].key pivot, m > j. It is assumed that list[left].key ≤ list[right+1].key. { if (left < right) { int i = left, j = right + 1, pivot = list[left].getKey(); do { do i++; while (list[i].getKey() < pivot); do j--; while (list[j].getKey() > pivot); if (i<j) InterChange(list, i, j); } while (i < j); InterChange(list, left, j); QuickSort(list, left, j–1); QuickSort(list, j+1, right); } }
Quick Sort Divide step: l scans the sequence from the left, and r from the right. A swap is performed when l is at an element larger than the pivot and r is at one smaller than the pivot.
Worst case: when the pivot does not divide the sequence in two At each step, the length of the sequence is only reduced by 1 Total running time General case: Time spent at level i in the tree is O(n) Running time: O(n) * O(height) Average case: O(n log n) Worst case: O(n^2) Quick Sort
Heap Sort 26 77 [1] [1] [2] 5 77 61 59 [2] [3] [3] 1 61 11 59 48 19 11 26 [5] [4] [5] [4] [6] [7] [7] [6] 15 48 19 15 1 5 [8] [9] [10] [10] [8] [9] (b) Initial heap (a) Input array
Heap Sort void adjust (Element* tree, const int root, const int n) // Adjust the binary tree with root root to satisfy the heap property. The left and right subtrees of root // already satisfy the heap property. No node has index greater than n. { Element e = tree[root]; int k = e.getKey(); for (int j = 2*root; j <= n; j *= 2) { if (j < n) if (tree[j].getKey() < tree[j+1].getKey()) j++; // compare max child with k. If k is max, then done. if (k >= tree[j].getKey()) break; tree[j/2] = tree[j]; // move jth record up the tree } tree[j/2] = e; }
void HeapSort (Element* list, const int n) // The list list = (list[1], …, list[n]) is sorted into nondecreasing order of the field key. { for (int i = n/2; i >= 1; i--) // convert list into a heap adjust(list, i, n); for (i = n-1; i >= 1; i--) // sort list { Element t = list[i+1]; // interchange list1 and list i+1 list[i+1] = list[1]; list[1] = t; adjust(list, 1, i); } } Heap Sort
Radix Sort • In a radix sort, we decompose the sort key using some radix r. • The number of bins needed is r. • Assume the records R1, R2, …, Rn to be sorted based on a radix of r. Each key has d digits in the range of 0 to r-1. • Assume each record has a link field. Then the records in the same bin are linked together into a chain: • f[i], 0 ≤ i ≤ r (the pointer to the first record in bin i) • e[i], (the pointer to the end record in bin i) • The chain will operate as a queue. • Each record is assumed to have an array key[d], 0 ≤ key[i] ≤ r, 0 ≤ i ≤ d.
Radix Sort void RadixSort (Element* list, const int d, const int n) { int e[radix], f[radix]; // queue pointers for (int i = 1; i <= n; i++) list[i].link = i + 1; // link into a chain starting at current list[n].link = 0; int current = 1; for (i = d – 1; i >= 0; i--) // sort on key key[i] { for (int j = 0; j < radix; j++) f[j] = 0; // initialize bins to empty queues for (; current; current = list[current].link) { // put records into queues int k = list[current].key[i]; if (f[k] == 0) f[k] = current; else list[e[k]].link = current; e[k] = current; } for (j = 0; f[j] == 0; j++); // find the first non-empty queue current = f[j]; int last = e[j]; for (int k = j+1; k < radix; k++){ // concatenate remaining queues if (f[k]){ list[last].link = f[k]; last = e[k]; } } list[last].link = 0; } } d passes O(n) O(r) O(d(n+r))
list[1] list[10] list[9] list[8] list[7] list[6] list[5] list[4] list[3] list[2] 179 208 306 93 859 984 55 9 271 33 e[0] e[1] e[2] e[3] e[4] e[5] e[6] e[7] e[8] e[9] 9 33 859 271 93 984 55 306 208 179 f[0] f[1] f[2] f[3] f[4] f[5] f[6] f[7] f[8] f[9] list[1] list[10] list[9] list[8] list[7] list[6] list[5] list[4] list[3] list[2] 271 93 33 984 55 306 208 179 859 9 Radix Sort
list[1] list[10] list[9] list[8] list[7] list[6] list[5] list[4] list[3] list[2] 271 93 33 984 55 306 208 179 859 9 e[0] e[1] e[2] e[3] e[4] e[5] e[6] e[7] e[8] e[9] 9 208 859 179 306 33 55 271 984 93 list[1] list[10] list[9] f[0] f[1] f[2] f[3] f[4] f[5] f[6] f[7] list[8] f[8] f[9] list[7] list[6] list[5] list[4] list[3] list[2] 306 208 9 33 55 859 271 179 984 93 Radix Sort
list[1] list[10] list[9] list[8] list[7] list[6] list[5] list[4] list[3] list[2] 306 208 9 33 55 859 271 179 984 93 e[0] e[1] e[2] e[3] e[4] e[5] e[6] e[7] e[8] e[9] 93 55 33 271 9 179 208 859 984 306 f[0] f[1] f[2] f[3] f[4] f[5] f[6] f[7] f[8] f[9] list[1] list[10] list[9] list[8] list[7] list[6] list[5] list[4] list[3] list[2] 9 33 55 93 179 208 271 306 859 948 Radix Sort
Radix Sort Example • Problem: sort 1 million 64-bit numbers • Treat as four-digit radix 2^16 numbers • Can sort in just four passes with radix sort! • Running time: 4( 1 million + 2^16 ) 4 million operations • Compare with typical O(n lg n) comparison sort • Requires approx lg n = 20 operations per number being sorted • Total running time 20 million operations
Radix Sort • In general, radix sort based on bucket sort is • Asymptotically fast (i.e., O(n)) • Simple to code • A good choice • Fast, Stable, Simple • Can radix sort be used on floating-point numbers?