关键词:插入冒泡选择、希尔归并快排、堆排序
倒着讲
1.堆排序
1.1有关堆与优先队列,看这里堆与优先队列
1.2堆排序的思想:
最大堆,每次把根从堆中取出来删去,然后从新建堆,并把取出来的元素放到数组的最后
那么最大的元素被放到n-1的位置,第二大的元素被放到n-2的位置。。。直到最后,数组就变成的由小到大的顺序
1.3算法复杂度
最好最差平均都是O(nlogn)
1.4核心代码
void heapsort(int A[], int n)
{
int maxval;
Heap H(A, n, n);
for (int i = 0; i < n; i++)
maxval = H.removefirst();
}
2.快速排序
2.1快排的思想:
快排的思想可以由BST得来,在BST中,左子树的值都小于根节点,右子树的值都大于等于根节点,因此检索的时候很快很方便。但问题在于二叉树空间占用太大,而且很容易变得不平衡。
因此,产生了快排的思想:
引入一个轴值pivot,这个值类似于BST中的根节点。把数组中小与pivot的值放到pivot的左边,而大于等于pivot的值放到其右边。在利用该思想,分别对轴值左边的部分和右边的部分排序。直到左边和右边的长度<=1.
具体实现的时候,由于不知道有多少个元素比轴值大,多少个元素比轴值小
因此每次把轴值先交换的最后,然后用两个指针,一个从左往右,一个从右往左,如果遇到左边指针指向的值大于轴值,右边指向的值小与轴值,交换两个元素,直到左右指针相遇,就是轴值应该在的位置,在把轴值换回来。
2.2实现代码(代码经过测试)
int findPivot(int A[], int i, int j)
{
return (i + j) / 2;
}
int partition(int A[], int l, int r, int p)
{
do {
while (A[++l] < p);
while (l<r&&A[--r]>p);
swap(A, l, r);
} while (l < r);
return l;
}
void qsort(int A[], int i, int j)
{
if (j<=i)return;
int index = findPivot(A, i, j);
swap(A, index, j);
int k = partition(A, i - 1, j, A[j]);
swap(A, k, j);
qsort(A, i, k - 1);
qsort(A, k + 1, j);
}
3.归并排序
3.1思想;
分治的思想。把原数组分成两个子数组,对子数组排序,然后在把两个数组合并起来。
其实该算法的关键就在合并上:把两个已经有序的数组合并成一个有序的数组
实现思想就是用两个指针分别指向这两个数组的开头,然后比较两指针指向的值,选着合适的放入要合并的新数组中并且将指针后移。
3.2实现代码(经过测试)
void mergeSort(int A[], int temp[], int left, int right)
{
if (left == right)return;
int mid = (left + right) / 2;
mergeSort(A, temp, left, mid);
mergeSort(A, temp, mid + 1, right);
for (int i = left; i <= right; i++)
temp[i] = A[i];
int i1 = left, i2 = mid + 1;
for (int curr=left;curr<=right;curr++)
{
if (i1 == mid + 1)
A[curr] = temp[i2++];
else if (i2 > right)
A[curr] = temp[i1++];
else if (temp[i1] < temp[i2])
A[curr] = temp[i1++];
else
A[curr] = temp[i2++];
}
}
4.希尔排序
4. 1思想:
希尔排序可以看做是对插入排序的优化。因为插入排序对于
基本有序的序列很快,并且比较适用于长度比较小的序列。
由以上两个特点,得出希尔排序的思想:
把大序列分成小序列,对小序列插入排序,使整个大序列尽可能的变得基本有序。
4.2代码(经过测试)
//按从小到大排序
void insort(int A[], int n, int incr)
{
for (int i = incr; i < n; i += incr)
for (int j = i; j >= incr && (A[j - incr] > A[j]); j -= incr)
swap(A, j - incr, j);
}
void shellsort(int A[], int n)
{
for (int i = n / 2; i>2; i /= 2)
for (int j = i; j >= 0; j--)
{
insort(&A[j], n - j, i);
}
insort(A, n, 1);
}
5.插入、冒泡、选择排序
5.1插入排序
思想:把新的元素与前面已经排好序的子序列进行比较,插入到合适的位置
代码:把4.2中,insort函数incr置成1,就是插入排序的代码
5.2冒泡排序
思想:每一次最小的元素就像气泡一样冒到数组的最前面
代码:
void bublesort(int A[], int n)
{
for (int i = 0; i < n - 1; i++)
for (int j = i+1; j < n; j++)
if (A[j] < A[i])
swap(A, i, j);
}
5.3选择
思想:选择排序是对冒泡排序的一种优化,每次记住最小元素的位置,到最后再进行交换
代码:
void selectSort(int A[], int n)
{
for (int i = 0; i < n; i++)
{
int min = i;
for (int j = n - 1; j > i; j--)
{
if (A[j] < A[min])
min = j;
}
swap(A, i, min);
}
}