找工作-基本查找排序算法总结

来源:互联网 发布:淘宝运动衣 编辑:程序博客网 时间:2024/05/29 23:45

每次找工作都感觉要复习下这些东西,常常想,这些神奇的玩意怎么就被想出来的!

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

1,常见排序算法:

排序的分类就不写了,各种分类,其实常用的就那么几种。

1.1  插入排序:

void insert_sort(int *a, int len) {int tmp;for (int i = 1; i < len; ++i) {for (int j = i; j > 0; --j) {if (a[j] < a[j-1]) {tmp = a[j];a[j] = a[j-1];a[j-1] = tmp;}else {break;}}}}

平均和最差时间代价均为θ(n²)

1.2 冒泡排序:

void bubblesort(int *a, int len) {int tmp,j,k;k = len;int flag = true;while (flag) {flag = false;for (j = 1; j < k; ++j) {if (a[j-1] > a[j]) {tmp = a[j-1];a[j-1] = a[j];a[j] = tmp;flag = true;}}--k;}}
该改进版来自:点击打开链接

平均和最差时间代价均为θ(n²)

1.3 选择排序;

void selectsort(int *a, int len) {int tmp,index;for (int i = 0; i < len; ++i) {index = i;for (int j = i+1; j < len; ++j) {if (a[j] < a[index]) {index = j;}}if (index != i) {tmp = a[i];    a[i] = a[index];    a[index] = tmp;}}}

平均和最差时间代价均为θ(n²)

备注:选择排序 是对 冒泡的改进,它使用了一个索引记录比较的结果,在一论遍历结束时才执行一次交换。

所以,对于交换代价比较大的问题,效果很明显。


1.4 shell排序

void insertsort_ex(int *a, int len, int incr) {int tmp;for (int i = incr; i < len; i += incr) {for (int j = i; j >= incr; j -= incr) {if (a[j] < a[j-incr]) {tmp = a[j];a[j] = a[j-incr];a[j-incr] = tmp;}else {break;}}}}void shellsort(int *a, int len) {for (int i = len/2; i > 2; i /= 2) {for (int j = 0; j < i; j++) {insertsort_ex(&a[j],len-j,i);}}insertsort_ex(a,len,1);}

shell排序利用了插入排序的最佳性能,首先将序列变成基本有序,最后再用插入排序。

shell排序 增量的选择很重要,参考点击打开链接

1.5 快速排序

int partition(int *a, int l, int r) {int low = l;int hi = r;int pivot = a[low];for (;low < hi;) {while(low < hi && a[hi] >= pivot)--hi;a[low] = a[hi];while(low < hi && a[low] <= pivot)++low;a[hi] = a[low];}a[low] = pivot;return low;}void qsort(int *a, int low, int high) {if (low < high) {int p = partition(a,low,high);qsort(a,low,p-1);qsort(a,p+1,high);}}

最差 O(n²),平均:θ(nlogn)

ps:可以改成尾递归形式。


1.6 堆排序

void HeapAdjust(int *a,int i,int size)  //调整堆 {int lchild=2*i+1;       //i的左孩子节点序号 int rchild=2*i+2;     //i的右孩子节点序号 int max=i;            //临时变量 if(i<=(size-1)/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-1)/2;i>=0;i--)    //非叶节点最大序号值为size/2 {HeapAdjust(a,i,size);    }    } void HeapSort(int *a,int size)    //堆排序 {int i;BuildHeap(a,size);for(i=size-1;i>=1;i--){//cout<<a[1]<<" ";swap(a[0],a[i]);           //交换堆顶和最后一个元素,即每次将剩余元素中的最大者放到最后面 //BuildHeap(a,i-1);        //将余下元素重新建立为大顶堆 HeapAdjust(a,0,i);      //重新调整堆顶节点成为大顶堆}} 
上述代码参考http://www.cnblogs.com/dolphin0520/archive/2011/10/06/2199741.html
不过我做了两处修改:修改为最大堆,升序输出;

修改根节点和孩子节点的对应关系,这样根节点保存在数组的第一个位置。

最佳、平均、最差时间代价都为O(n*logn);

引用:“堆排序其实也是一种选择排序,是一种树形选择排序。只不过直接选择排序中,为了从R[1...n]中选择最大记录,需比较n-1次,然后从R[1...n-2]中选择最大记录需比较n-2次。事实上这n-2次比较中有很多已经在前面的n-1次比较中已经做过,而树形选择排序恰好利用树形的特点保存了部分前面的比较结果,因此可以减少比较次数。对于n个关键字序列,最坏情况下每个节点需比较log2(n)次,因此其最坏情况下时间复杂度为nlogn。堆排序为不稳定排序,不适合记录较少的排序”

1.7 归并排序

//将有二个有序数列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++];elsetemp[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 - first) / 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;}

归并排序最佳、平均、最差时间代价都为O(n*logn),该排序不太适合内存排序,因为不仅要开辟额外的线性内存,而且还要来回拷贝数据,想想还是算了吧。。。。

但是,归并排序是稳定的哦。

但是,归并排序中的merge是很多外部排序的基础哦。

0 0
原创粉丝点击