1.这道题有关于数组的排序问题,关于sorting,主要有以下几种algorithm:
(以下很多代码来自geekforgeek https://www.geeksforgeeks.org/sorting-algorithms/)
- selection sort
选择排序算法通过从未排序部分重复查找最小元素(考虑升序)并将其放在开头来对数组进行排序。该算法在给定数组中维护两个子数组。
1)已排序的子数组。
2)未排序的剩余子数组。
在选择排序的每次迭代中,都会从未排序的子数组中选取最小元素(考虑升序)并将其移至已排序的子数组。
arr [] = 64 25 12 22 11
//在arr [0 ... 4]中查找最小元素
//并将其放在开头
11 25 12 22 64
//在arr [1 ... 4]中查找最小元素
//并将其放在arr [1 ... 4]的开头
11 12 25 22 64
//在arr [2 ... 4]中找到最小元素
//并将其放在arr [2 ... 4]的开头
11 12 22 25 64
//在arr [3 ... 4]中查找最小元素
//并将其放在arr [3 ... 4]的开头
11 12 22 25 64
2.bubble sort
实质与selection sort 相反, 先排号最右边的最大数,因此为两个for loop
看下来自geekfor geek的简单代码
void swap(int *xp, int *yp)
{
int temp = *xp;
*xp = *yp;
*yp = temp;
}
// A function to implement bubble sort
void bubbleSort(int arr[], int n)
{
int i, j;
for (i = 0; i < n-1; i++)
// Last i elements are already in place
for (j = 0; j < n-i-1; j++)
if (arr[j] > arr[j+1])
swap(&arr[j], &arr[j+1]);
}
- recursive bubble sort
递归的想法。
1)基本情况:如果数组大小为1,则返回。
2)一遍普通气泡排序。此遍可修复当前子数组的最后一个元素。
3)对于除当前子数组的最后一个元素之外的所有元素,均重复执行。
// A function to implement bubble sort
void bubbleSort(int arr[], int n)
{
// Base case
if (n == 1)
return;
// One pass of bubble sort. After
// this pass, the largest element
// is moved (or bubbled) to end.
for (int i=0; i<n-1; i++)
if (arr[i] > arr[i+1])
swap(arr[i], arr[i+1]);
// Largest element is fixed,
// recur for remaining array
bubbleSort(arr, n-1);
}
4.insertion sort
arr []
循环,从i = 1到n-1。
……a)选择元素arr [i]并将其插入排序后的序列arr [0…i-1]
原理:
1)从i=1开始到最后一个元素, 用whileloop找到新元素需要在的位置,期间,将大于key 的都位置+1,为后面找到位置腾出空位出来
/* Function to sort an array using insertion sort*/
void insertionSort(int arr[], int n)
{
int i, key, j;
for (i = 1; i < n; i++)
{
key = arr[i];
j = i - 1;
/* Move elements of arr[0..i-1], that are
greater than key, to one position ahead
of their current position */
while (j >= 0 && arr[j] > key)
{
arr[j + 1] = arr[j];
j = j - 1;
}
arr[j + 1] = key;
}
}
5.recursive insertion sort
总结一下就是recursive需要考虑在n-1重复的案例的先后,比如bubble sort是在筛选出最大数以后整理剩下的n-1 个重复项, 而insertion sort是需要整理好n-1个重复项得到倒数第二个元素,然后再添加back。
// Recursive function to sort an array using
// insertion sort
void insertionSortRecursive(int arr[], int n)
{
// Base case
if (n <= 1)
return;
// Sort first n-1 elements
insertionSortRecursive( arr, n-1 );
// Insert last element at its correct position
// in sorted array.
int last = arr[n-1];
int j = n-2;
/* Move elements of arr[0..i-1], that are
greater than key, to one position ahead
of their current position */
while (j >= 0 && arr[j] > last)
{
arr[j+1] = arr[j];
j--;
}
arr[j+1] = last;
}
- merge sort
像QuickSort一样,合并排序是一种分而治之算法。它将输入数组分为两半,将自己称为两半,然后合并两个排序的两半。merge()函数用于合并两个半部分。
// Merges two subarrays of arr[].
// First subarray is arr[l..m]
// Second subarray is arr[m+1..r]
void merge(int arr[], int l, int m, int r)
{
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
/* create temp arrays */
int L[n1], R[n2];
/* Copy data to temp arrays L[] and R[] */
for (i = 0; i < n1; i++)
L[i] = arr[l + i];
for (j = 0; j < n2; j++)
R[j] = arr[m + 1+ j];
/* Merge the temp arrays back into arr[l..r]*/
i = 0; // Initial index of first subarray
j = 0; // Initial index of second subarray
k = l; // Initial index of merged subarray
while (i < n1 && j < n2)
{
if (L[i] <= R[j])
{
arr[k] = L[i];
i++;
}
else
{
arr[k] = R[j];
j++;
}
k++;
}
/* Copy the remaining elements of L[], if there
are any */
while (i < n1)
{
arr[k] = L[i];
i++;
k++;
}
/* Copy the remaining elements of R[], if there
are any */
while (j < n2)
{
arr[k] = R[j];
j++;
k++;
}
}
/* l is for left index and r is right index of the
sub-array of arr to be sorted */
void mergeSort(int arr[], int l, int r)
{
if (l < r)
{
// Same as (l+r)/2, but avoids overflow for
// large l and h
int m = l+(r-l)/2;
// Sort first and second halves
mergeSort(arr, l, m);
mergeSort(arr, m+1, r);
merge(arr, l, m, r);
}
}
7.quick sort
把最后一个元素放到恰当的位置然后分成两部分循环进行sorting
// A utility function to swap two elements
void swap(int* a, int* b)
{
int t = *a;
*a = *b;
*b = t;
}
/* This function takes last element as pivot, places
the pivot element at its correct position in sorted
array, and places all smaller (smaller than pivot)
to left of pivot and all greater elements to right
of pivot */
int partition (int arr[], int low, int high)
{
int pivot = arr[high]; // pivot
int i = (low - 1); // Index of smaller element
for (int j = low; j <= high - 1; j++)
{
// If current element is smaller than the pivot
if (arr[j] < pivot)
{
i++; // increment index of smaller element
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[high]);
return (i + 1);
}
/* The main function that implements QuickSort
arr[] --> Array to be sorted,
low --> Starting index,
high --> Ending index */
void quickSort(int arr[], int low, int high)
{
if (low < high)
{
/* pi is partitioning index, arr[p] is now
at right place */
int pi = partition(arr, low, high);
// Separately sort elements before
// partition and after partition
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
8 heap sort
在这之前需要先明白它是怎么由数组形式变成树图的, root,第一层的左,第一层的右, 第二层的左,第二层的右。
Input data: 4, 10, 3, 5, 1
4(0)
/ \
10(1) 3(2)
/ \
5(3) 1(4)
括号中的数字表示数组中的索引
数据表示。
将heapify过程应用于索引1:
4(0)
/ \
10(1)3(2)
/ \
5(3)1(4)
将heapify过程应用于索引0:
10(0)
/ \
5(1)3(2)
/ \
4(3)1(4)
heapify过程以递归方式调用自身以构建堆
以自上而下的方式。
代码如下
// To heapify a subtree rooted with node i which is
// an index in arr[]. n is size of heap
void heapify(int arr[], int n, int i)
{
int largest = i; // Initialize largest as root
int l = 2*i + 1; // left = 2*i + 1
int r = 2*i + 2; // right = 2*i + 2
// If left child is larger than root
if (l < n && arr[l] > arr[largest])
largest = l;
// If right child is larger than largest so far
if (r < n && arr[r] > arr[largest])
largest = r;
// If largest is not root
if (largest != i)
{
swap(arr[i], arr[largest]);
// Recursively heapify the affected sub-tree
heapify(arr, n, largest);
}
}
// main function to do heap sort
void heapSort(int arr[], int n)
{
// Build heap (rearrange array)
for (int i = n / 2 - 1; i >= 0; i--)
heapify(arr, n, i);
// One by one extract an element from heap
for (int i=n-1; i>=0; i--)
{
// Move current root to end
swap(arr[0], arr[i]);
// call max heapify on the reduced heap
heapify(arr, i, 0);
}
}
heapify 函数做的是先得到最大数的index, 然后进行循环subtree,
heap函数做的是先建立heap,然后把最大数置换到最后,然后对剩下的n-1个元素进行重新heapify。