1、冒泡排序
非递归实现
void bubbleSort(int *array,int len) {
int tmp;
bool flag;
for (int i= len-1; i > 0; i--) {
flag = false;
for (int j = 0; j < i; j++) {
if (array[j] > array[j+1]) {
flag = true;
tmp = array[j];
array[j] = array[j+1];
array[j+1] = tmp;
}
}
if (flag == false) {
break;
}
}
}
递归实现
void bubbleSort(int *array,int len) {
if (len > 1) {
for (int i = 0; i < len-1;i++) {
if (array[i] > array[i+1]) {
int tmp = array[i];
array[i] = array[i+1];
array[i+1] = tmp;
}
}
bubbleSort(array,len-1);
}
}
-------思路:相邻元素对比大的往下挪,下次再从size-1数组中找次大的-------------
2、插入排序
非递归实现
void insSort(int *array,int len) {
int index;
int low;
for (int i= 1; i < len; i++) {
if (array[i] < array[i-1]) {
index = array[i];
low = i-1;
while (index < array[low] && low >= 0) {
array[low+1] = array[low];
low--;
}
if (low != i-1) {
array[low+1] = index;
}
}
}
递归实现
void insSort(int *array, int len,int pos) {
if (pos > len-1) {
return;
}
if (array[pos] < array[pos-1]) {
int key = array[pos];
int p = pos-1;
while (array[p] >= key && p >= 0) {
array[p+1] = array[p];
p--;
}
array[p+1] = key;
}
insSort(array,len,pos+1);
}
-------思路:每次从已经排序好的k个数组中添加第k+1个数据,从k数组中以该数值为第k+1数据为标杆找到该的数据的正确位置,比之大的数据往后挪一个位置。-------
3、堆排序
/*堆排序(大顶堆) 2011.9.14*/
#include <iostream>
#include<algorithm>
using namespace std;
void HeapAdjust(int *a,int i,int size) //调整堆
{
int lchild=2*i; //i的左孩子节点序号
int rchild=2*i+1; //i的右孩子节点序号
int max=i; //临时变量
if(i<=size/2) //如果i是叶节点就不用进行调整
{
if(lchild<=size&&a[lchild]>a[max])
{
max=lchild;
}
if(rchild<=size&&a[rchild]>a[max])
{
max=rchild;
}
if(max!=i)
{
swap(a[i],a[max]);
HeapAdjust(a,max,size); //避免调整之后以max为父节点的子树不是堆
}
}
}
void BuildHeap(int *a,int size) //建立堆
{
int i;
for(i=size/2;i>=1;i--) //非叶节点最大序号值为size/2
{
HeapAdjust(a,i,size);
}
}
void HeapSort(int *a,int size) //堆排序
{
int i;
BuildHeap(a,size);
for(i=size;i>=1;i--)
{
//cout<<a[1]<<" ";
swap(a[1],a[i]); //交换堆顶和最后一个元素,即每次将剩余元素中的最大者放到最后面
//BuildHeap(a,i-1); //将余下元素重新建立为大顶堆
HeapAdjust(a,1,i-1); //重新调整堆顶节点成为大顶堆
}
}
int main(int argc, char *argv[])
{
//int a[]={0,16,20,3,11,17,8};
int a[100];
int size;
while(scanf("%d",&size)==1&&size>0)
{
int i;
for(i=1;i<=size;i++)
cin>>a[i];
HeapSort(a,size);
for(i=1;i<=size;i++)
cout<<a[i]<<"";
cout<<endl;
}
return 0;
}
-----------------------------求最大的k个数-----------------
#include <iostream> #include<algorithm> using namespace std; void HeapAdjust(int *a,int i,int size) //调整堆 { int lchild=2*i; //i的左孩子节点序号 int rchild=2*i+1; //i的右孩子节点序号 int min=i; //临时变量 if(i<=size/2) //如果i是叶节点就不用进行调整 { if(lchild<=size&&a[lchild]<a[min]) { min=lchild; } if(rchild<=size&&a[rchild]<a[min]) { min=rchild; } if(min!=i) { swap(a[i],a[min]); HeapAdjust(a,min,size); //避免调整之后以min为父节点的子树不是堆 } } }
void BuildHeap(int *a,int size) //建立堆 { int i; for(i=size/2;i>=1;i--) //非叶节点最大序号值为size/2 { HeapAdjust(a,i,size); } }
void HeapSort(int *a,int size,int nselect) //堆排序 { int i; BuildHeap(a,nselect); for(i = nselect+1;i <= size;i++) { if (a[1] < a[i]) { swap(a[i],a[1]); HeapAdjust(a,1,nselect); } }
}
int main(int argc, char *argv[]) { //int a[]={0,16,20,3,11,17,8}; int a[100]; int nselect = atoi(argv[1]); int size; while(scanf("%d",&size)==1&&size>0) { int i; for(i=1;i<=size;i++) cin>>a[i]; HeapSort(a,size,nselect); for(i=1;i<=nselec;i++) cout<<a[i]<<" "; cout<<endl; } return 0; }
-----------思路:先用k个数组成最小堆,然后判断后面的是否小于第一个如果小于则忽略,否则替换第一个然后调整最小堆---------
4、归并排序
- //将有二个有序数列a[first...mid]和a[mid...last]合并。
- void mergearray(int a[], int first, int mid, int last, int temp[])
- {
- int i = first, j = mid + 1;
- int m = mid, n = last;
- int k = 0;
- while (i <= m && j <= n)
- {
- if (a[i] <= a[j])
- temp[k++] = a[i++];
- else
- temp[k++] = a[j++];
- }
- while (i <= m)
- temp[k++] = a[i++];
- while (j <= n)
- temp[k++] = a[j++];
- for (i = 0; i < k; i++)
- a[first + i] = temp[i];
- }
- void mergesort(int a[], int first, int last, int temp[])
- {
- if (first < last)
- {
- int mid = (first + last) / 2;
- mergesort(a, first, mid, temp); //左边有序
- mergesort(a, mid + 1, last, temp); //右边有序
- mergearray(a, first, mid, last, temp); //再将二个有序数列合并
- }
- }
- bool MergeSort(int a[], int n)
- {
- int *p = new int[n];
- if (p == NULL)
- return false;
- mergesort(a, 0, n - 1, p);
- delete[] p;
- return true;
- }
----------思路:分而治之,先分再和,递归分,和时将两个排序好的数组再借用临时数组重组,之后再重新复制给原数组---------5、快速排序void quickSort(int *array, int l, int r) { if (l < r) { int i = l, j = r, index = array[l]; while (i < j) { while (array[j] >= index) { j--; } if (i < j) { array[i++] = array[j]; } while (array[i] < index) { i++; } if (i < j) { array[j--] = array[i]; } } array[i] = index; quickSort(array,l,i-1); quickSort(array,i+1,r); } }----思路:每次都以数组中的某一个值(可以随机)作为标杆,依次从左至右遍历将比它小的排在左边,大的排右边,可以得到标杆应该放的位置再递归----6、选择排序void selSort(int *array,int len) { int index; int tmp; for (int i= len-1; i > 0; i--) { index = i; for (int j = 0; j < i; j++) { if (array[j] > array[index]) { index = j; } } if (i != index) { tmp = array[i]; array[i] = array[index]; array[index] = tmp; } } }-----思路:和冒泡排序有点类似,每次从数组中找最大的数据排在最后,但是不需要像冒泡排序挪位置------
===========================各种排序算法的比较============================
1.稳定性比较
插入排序、冒泡排序、二叉树排序、二路归并排序及其他线形排序是稳定的
选择排序、希尔排序、快速排序、堆排序是不稳定的
2.时间复杂性比较
平均情况 | 最好情况 | 最坏情况 | |
归并排序 | O(nlogn) | O(nlogn) | O(nlogn) |
基数排序 | O(n) | O(n) | O(n) |
快速排序 | O(nlogn) | O(nlogn) | O(n2) |
希尔排序 | O(n1.5) | O(n) | O(n1.5) |
插入排序 | O(n2) | O(n) | O(n2) |
选择排序 |
O(n2) | O(n2) | O(n2) |
3.辅助空间的比较
线形排序、二路归并排序的辅助空间为O(n),其它排序的辅助空间为O(1);
4.其它比较
插入、冒泡排序的速度较慢,但参加排序的序列局部或整体有序时,这种排序能达到较快的速度。
反而在这种情况下,快速排序反而慢了。
当n较小时,对稳定性不作要求时宜用选择排序,对稳定性有要求时宜用插入或冒泡排序。
若待排序的记录的关键字在一个明显有限范围内时,且空间允许是用桶排序。
当n较大时,关键字元素比较随机,对稳定性没要求宜用快速排序。
当n较大时,关键字元素可能出现本身是有序的,对稳定性有要求时,空间允许的情况下。
宜用归并排序。
当n较大时,关键字元素可能出现本身是有序的,对稳定性没有要求时宜用堆排序。
*************************************************************************************
相关知识介绍(所有定义只为帮助读者理解相关概念,并非严格定义): 1、稳定排序和非稳定排序
简单地说就是所有相等的数经过某种排序方法后,仍能保持它们在排序之前的相对次序,我们就 说这种排序方法是稳定的。反之,就是非稳定的。 比如:一组数排序前是a1,a2,a3,a4,a5,其中a2=a4,经过某种排序后为a1,a2,a4,a3,a5, 则我们说这种排序是稳定的,因为a2排序前在a4的前面,排序后它还是在a4的前面。假如变成a1,a4, a2,a3,a5就不是稳定的了。
2、内排序和外排序
在排序过程中,所有需要排序的数都在内存,并在内存中调整它们的存储顺序,称为内排序; 在排序过程中,只有部分数被调入内存,并借助内存调整数在外存中的存放顺序排序方法称为外排序。
3、算法的时间复杂度和空间复杂度
所谓算法的时间复杂度,是指执行算法所需要的计算工作量。 一个算法的空间复杂度,一般是指执行这个算法所需要的内存空间。