三种排序:快排,归并,堆排

转自:http://www.cnblogs.com/LUO77/p/5798149.html

(一)快排

快排考的是最多次的。之前看大神写的算法很简单,思想也很好。就一直用他的思想去思考快排了。挖坑法。

拿走第一个元素作为标兵元素,即挖坑,然后从后面找一个比它小的填坑,然后又形成一个坑,再从前面找一个比标兵大的填坑,又形成一个坑。……最后一个坑填入标兵就好。

然后就是递归了。再在标兵左边排序,右边排序。

 1 void QSort(int* num, int start, int end) {
 2     if(num == NULL||start >= end)
 3         return;
 4     int tmp = num[start];
 5     int i = start, j = end;
 6     while (i<j) {
 7         while (i<j&&num[j]>tmp) {
 8             j--;
 9         }
10         if (i<j)
11             num[i++] = num[j];
12         while (i<j&&num[i]<tmp) {
13             i++;
14         }
15         if (i<j)
16             num[j--] = num[i];
17     }
18     num[i] = tmp;
19     QSort(num, start, i - 1);
20     QSort(num, i + 1, end);
21 }

归并:

归并的思想就是分治-组合。

先divide,然后merge。

divide的思想比较简单,找到middle,再划分A[start,,,,,middle],A[middle+1...end]

对于左边在递归划分,划分直至只剩一个元素,然后再merge。merge的时候需要一个临时数组。merge的时候是A[first...middle]和A[middle+1……end]合并。

对于右边在递归划分,划分直至只剩一个元素,然后再merge。

左边和右边都有序了,然后再将两个数组合并为一个数组。最后整个数组都有序了。(先处理左边,再处理右边)

 1 void merge(int* A, int start, int middle, int last, int *tmp) {
 2
 3     int i1 = start, j1 = middle;
 4     int i2 = middle+1, j2 = last;
 5     int index = 0;
 6     while (i1<=j1&&i2<=j2) {
 7         if (A[i1]<=A[i2])
 8             tmp[index++] = A[i1++];
 9         else tmp[index++] = A[i2++];
10     }
11     while (i1 <= j1) {
12         tmp[index++] = A[i1++];
13     }
14     while (i2 <= j2) {
15         tmp[index++] = A[i2++];
16     }
17     for (int i = 0; i<index; i++) {
18         A[start + i] = tmp[i];
19     }
20     return;
21 }
22 void divide(int* A, int start, int end, int* tmp) {
23     if (start<end) {
24         int middle = (start + end) / 2;
25         divide(A, start, middle, tmp);
26         divide(A, middle+1, end, tmp);
27         merge(A, start, middle, end, tmp);
28     }
29 }
30 void mergesort(int* A, int size) {
31     if (A == NULL || size == 0 || size == 1)
32         return;
33     int* tmp = new int[size];
34     divide(A, 0, size - 1, tmp);
35     delete[] tmp;
36     return;
37 }

堆排序(以最大堆为例子):
1.首先要构建一个最大堆(从size/2-1位置开始维护堆,叶子节点默认已经是一个最大堆了,维护到根节点,则已经构成一个最大堆)
2.交换根节点(此时根节点是最大值),和最后一个节点,破坏了最大堆的性质,此时继续维护最大堆(维护最大堆的过程就是类似直接插入排序,找到维护点合适插入的位置,保证最大堆性质不被破坏就好)
3.循环交换最后一个节点和根节点,每次维护最大堆的规模减一(找到最大,找到次大,次次大……),到最后到根节点,也就排序完成了。

 1 void swap(int& a, int& b) {
 2     a ^= b;
 3     b ^= a;
 4     a ^= b;
 5 }
 6 void HeapAdjust(int* A, int size, int start) {
 7     int i = start;
 8     int j = 2 * i + 1;
 9     int tmp = A[i];
10     while (j <= size) {
11         if (j + 1 <= size&&A[j + 1]>A[j])
12             j++;
13         if (A[j] <= tmp)
14             break;
15         A[i] = A[j];
16         i = j;
17         j = 2 * i + 1;
18     }
19     A[i] = tmp;
20     return;
21 }
22
23 void CreateHeap(int* A, int size) {
24     for (int i = size / 2 - 1; i >= 0; i--)
25         HeapAdjust(A, size - 1, i);
26 }
27
28 void HeapSort(int* A, int size) {
29     if (A == NULL || size == 0 || size == 1)
30         return;
31     CreateHeap(A, size);
32     for (int i = size - 1; i >= 1;) {
33         swap(A[0], A[i--]);
34         HeapAdjust(A, i, 0);
35     }
36 }

原文地址:https://www.cnblogs.com/demian/p/8206734.html

时间: 2025-01-12 05:31:10

三种排序:快排,归并,堆排的相关文章

三种排序方法用java实现

用三种方法实现几个数的排序:冒泡排序,选择排序,调用Java里的库函数 1. 冒泡排序:顾名思义,就是将小的数一步一步往上冒,大的数一个个往下沉,下面是自己写的对冒泡排序的理解,字丑将就看一下吧. 2.选择排序:以从小到大为例,定义一个变量min_inter,用于记录最小值的下标,找到最小的数放在第0位,第二小放在第1位,后面依次. 3.直接调用:Arrays.sort(num3):需要导入import java.util.Arrays: 下面是代码: 1 import java.util.Ar

JavaScript新手学习笔记3——三种排序方式(冒泡排序、插入排序、快速排序)

每种编程语言学到数组的时候,都会讲到排序算法,当时学C语言的时候,卡在排序算法.今天来总结一下javascript中如何实现三种排序算法. 1.冒泡排序(默认升序排列哦) 原理: 冒泡排序的原理,顾名思义,就是小数往上冒,大数往下沉.从第一个数开始,如果比第二个数大就交换位置,然后跟第三个数字进行比较大小,交换位置等. 举例一下,有数组[2,4,3,5,1] 第一次循环:2<4  不交换:4>3 交换:4<5不交换:5>1交换,故结果是[2,3,4,1,5]; 第二次循环:2<

Java常见的几种排序算法-插入、选择、冒泡、快排、堆排等

本文就是介绍一些常见的排序算法.排序是一个非常常见的应用场景,很多时候,我们需要根据自己需要排序的数据类型,来自定义排序算法,但是,在这里,我们只介绍这些基础排序算法,包括:插入排序.选择排序.冒泡排序.快速排序(重点).堆排序.归并排序等等.看下图: 给定数组:int data[] = {9,2,7,19,100,97,63,208,55,78} 一.直接插入排序(内部排序.O(n2).稳定) 原理:从待排序的数中选出一个来,插入到前面的合适位置. [java] view plain copy

常见的几种排序算法-插入、选择、冒泡、快排、堆排等

排序是一个非常常见的应用场景,很多时候,我们需要根据自己需要排序的数据类型,来自定义排序算法,但是,在这里,我们只介绍这些基础排序算法,包括:插入排序.选择排序.冒泡排序.快速排序(重点).堆排序.归并排序等等.看下图: 给定数组:int data[] = {9,2,7,19,100,97,63,208,55,78} 一.直接插入排序(内部排序.O(n2).稳定) 原理:从待排序的数中选出一个来,插入到前面的合适位置. package com.xtfggef.algo.sort; public

python 快排,堆排,归并

#归并排序def mergeSort(a,L,R) :    if(L>=R) :        return    mid=((L+R)>>1)    mergeSort(a,L,mid)    mergeSort(a,mid+1,R)    p=L    q=mid+1    t=[]    while(p<=mid and q<=R) :        if a[p]<=a[q] :            t.append(a[p])            p+=

快排,堆排与归并排序

快排: Parition函数用于进行一次快排,本次快排将某个元素放在它应该呆在的位置pos.pos左侧全比它小,pos右侧全比它大. Parition中,设置low指针与high指针,以待排元素为标杆,判断high指向元素是否大于待排元素,若小于则与low指向的元素交换,并切换到low指针.low指针此时指向刚交换过来的元素,其一定小于待排元素,然后low自加直到low指向的元素大于待排元素,此时再与high指向的元素交换,high指向的元素为之前一次low - high交换前low指向的元素:

排序算法的实现(归并,快排,堆排,希尔排序 O(N*log(N)))

今天跟着左老师的视频,理解了四种复杂度为 O(N*log(N))的排序算法,以前也理解过过程,今天根据实际的代码,感觉基本的算法还是很简单的,只是自己写的时候可能一些边界条件,循环控制条件把握不好. //对于一个int数组,请编写一个选择冒泡算法,对数组元素排序. //给定一个int数组A及数组的大小n,请返回排序后的数组. //测试样例: //[1, 2, 3, 5, 2, 3], 6 //[1, 2, 2, 3, 3, 5] #include <iostream> using namesp

三种排序算法(归并排序、快速排序,堆排序)

归并排序:建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序列:即先使每个子序列有序,再使子序列段间有序.若将两个有序表合并成一个有序表,称为二路归并. 归并排序算法稳定,数组需要O(n)的额外空间,链表需要O(log(n))的额外空间,时间复杂度为O(nlog(n)),算法不是自适应的,不需要对数据的随机读取. 工作原理: 1.申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后

7.20 函数III&amp;三种排序 Day13

1.选择排序 将某个特定值有序的放置在最终位置上---外层循环控制最终位置的序号,内层循环从外层循环序号处向后遍历,找到最小值. 2.插入排序 插入排序将某个特定值插入到值列的某个子集中,并重复该过程---外层循环控制要插入的数据(从第二个数到最后一个),内层循环控制前面已排好序的的值后移. 3.冒泡排序 重复比较相邻的两个元素,并在必要的时候交换双方位置.---外层循环控制每次冒泡到达的最终位置,内层循环交换元素