冒泡排序法和快速排序比较的算法 编写一个程序分别实现冒泡排序和快速排序算法。要求:两种排序算...

作者&投稿:迟货 (若有异议请与网页底部的电邮联系)
打你屁股,这么简单的问题都不认真研究一下。

冒泡排序是最慢的排序,时间复杂度是 O(n^2)。

快速排序是最快的排序。关于快速排序,我推荐你看看《代码之美》第二章:我编写过的最漂亮的代码。作者所说的最漂亮,就是指效率最高的。

--------------------------------摘自《代码之美》---------------

当我撰写关于分治(divide-and-conquer)算法的论文时,我发现C.A.R. Hoare的Quicksort算法(“Quicksort”,Computer Journal 5)无疑是各种Quicksort算法的鼻祖。这是一种解决基本问题的漂亮算法,可以用优雅的代码实现。我很喜欢这个算法,但我总是无法弄明白算法中最内层的循环。我曾经花两天的时间来调试一个使用了这个循环的复杂程序,并且几年以来,当我需要完成类似的任务时,我会很小心地复制这段代码。虽然这段代码能够解决我所遇到的问题,但我却并没有真正地理解它。
我后来从Nico Lomuto那里学到了一种优雅的划分(partitioning)模式,并且最终编写出了我能够理解,甚至能够证明的Quicksort算法。William Strunk Jr.针对英语所提出的“良好的写作风格即为简练”这条经验同样适用于代码的编写,因此我遵循了他的建议,“省略不必要的字词”(来自《The Elements of Style》一书)。我最终将大约40行左右的代码缩减为十几行的代码。因此,如果要回答“你曾编写过的最漂亮代码是什么?”这个问题,那么我的答案就是:在我编写的《Programming Pearls, Second Edition》(Addison-Wesley)一书中给出的Quichsort算法。在示例2-1中给出了用C语言编写的Quicksort函数。我们在接下来的章节中将进一步地研究和改善这个函数。
【示例】 2-1 Quicksort函数
void quicksort(int l, int u)
{ int i, m;
if (l >= u) return; 10
swap(l, randint(l, u));
m = l;
for (i = l+1; i <= u; i++)
if (x[i] < x[l])
swap(++m, i);
swap(l, m);
quicksort(l, m-1);
quicksort(m+1, u);
}
如果函数的调用形式是quicksort(0, n-1),那么这段代码将对一个全局数组x[n]进行排序。函数的两个参数分别是将要进行排序的子数组的下标:l是较低的下标,而u是较高的下标。函数调用swap(i,j)将会交换x[i]与x[j]这两个元素。第一次交换操作将会按照均匀分布的方式在l和u之间随机地选择一个划分元素。
在《Programming Pearls》一书中包含了对Quicksort算法的详细推导以及正确性证明。在本章的剩余内容中,我将假设读者熟悉在《Programming Pearls》中所给出的Quicksort算法以及在大多数初级算法教科书中所给出的Quicksort算法。
如果你把问题改为“在你编写那些广为应用的代码中,哪一段代码是最漂亮的?”我的答案还是Quicksort算法。在我和M. D. McIlroy一起编写的一篇文章("Engineering a sort function," Software-Practice and Experience, Vol. 23, No. 11)中指出了在原来Unix qsort函数中的一个严重的性能问题。随后,我们开始用C语言编写一个新排序函数库,并且考虑了许多不同的算法,包括合并排序(Merge Sort)和堆排序(Heap Sort)等算法。在比较了Quicksort的几种实现方案后,我们着手创建自己的Quicksort算法。在这篇文章中描述了我们如何设计出一个比这个算法的其他实现要更为清晰,速度更快以及更为健壮的新函数——部分原因是由于这个函数的代码更为短小。Gordon Bell的名言被证明是正确的:“在计算机系统中,那些最廉价,速度最快以及最为可靠的组件是不存在的。”现在,这个函数已经被使用了10多年的时间,并且没有出现任何故障。
考虑到通过缩减代码量所得到的好处,我最后以第三种方式来问自己在本章之初提出的问题。“你没有编写过的最漂亮代码是什么?”。我如何使用非常少的代码来实现大量的功能?答案还是和Quicksort有关,特别是对这个算法的性能分析。我将在下一节给出详细介绍。
2.2 事倍功半
Quicksort是一种优雅的算法,这一点有助于对这个算法进行细致的分析。大约在1980年左右,我与Tony Hoare曾经讨论过Quicksort算法的历史。他告诉我,当他最初开发出Quicksort时,他认为这种算法太简单了,不值得发表,而且直到能够分析出这种算法的预期运行时间之后,他才写出了经典的“Quicksoft”论文。
我们很容易看出,在最坏的情况下,Quicksort可能需要n2的时间来对数组元素进行排序。而在最优的情况下,它将选择中值作为划分元素,因此只需nlgn次的比较就可以完成对数组的排序。那么,对于n个不同值的随机数组来说,这个算法平均将进行多少次比较?
Hoare对于这个问题的分析非常漂亮,但不幸的是,其中所使用的数学知识超出了大多数程序员的理解范围。当我为本科生讲授Quicksort算法时,许多学生即使在费了很大的努力之后,还是无法理解其中的证明过程,这令我非常沮丧。下面,我们将从Hoare的程序开
11
始讨论,并且最后将给出一个与他的证明很接近的分析。
我们的任务是对示例2-1中的Quicksort代码进行修改,以分析在对元素值均不相同的数组进行排序时平均需要进行多少次比较。我们还将努力通过最短的代码、最短运行时间以及最小存储空间来得到最深的理解。
为了确定平均比较的次数,我们首先对程序进行修改以统计次数。因此,在内部循环进行比较之前,我们将增加变量comps的值(参见示例2-2)。
【示例2-2】 修改Quicksort的内部循环以统计比较次数。
for (i = l+1; i <= u; i++) {
comps++;
if (x[i] < x[l])
swap(++m, i);
}
如果用一个值n来运行程序,我们将会看到在程序的运行过程中总共进行了多少次比较。如果重复用n来运行程序,并且用统计的方法来分析结果,我们将得到Quicksort在对n个元素进行排序时平均使用了1.4 nlgn次的比较。
在理解程序的行为上,这是一种不错的方法。通过十三行的代码和一些实验可以反应出许多问题。这里,我们引用作家Blaise Pascal和T. S. Eliot的话,“如果我有更多的时间,那么我给你写的信就会更短。”现在,我们有充足的时间,因此就让我们来对代码进行修改,并且努力编写出更短(同时更好)的程序。
我们要做的事情就是提高这个算法的速度,并且尽量增加统计的精确度以及对程序的理解。由于内部循环总是会执行u-l次比较,因此我们可以通过在循环外部增加一个简单的操作来统计比较次数,这就可以使程序运行得更快一些。在示例2-3的Quicksort算法中给出了这个修改。
【示例2-3】 Quicksort的内部循环,将递增操作移到循环的外部
comps += u-l;
for (i = l+1; i <= u; i++)
if (x[i] < x[l])
swap(++m, i);
这个程序会对一个数组进行排序,同时统计比较的次数。不过,如果我们的目标只是统计比较的次数,那么就不需要对数组进行实际地排序。在示例2-4中去掉了对元素进行排序的“实际操作”,而只是保留了程序中各种函数调用的“框架”。
【示例2-4】将Quicksort算法的框架缩减为只进行统计
void quickcount(int l, int u)
{ int m;
if (l >= u) return;
m = randint(l, u);
comps += u-l;
quickcount(l, m-1);
quickcount(m+1, u);
}
12
这个程序能够实现我们的需求,因为Quichsort在选择划分元素时采用的是“随机”方式,并且我们假设所有的元素都是不相等的。现在,这个新程序的运行时间与n成正比,并且相对于示例2-3需要的存储空间与n成正比来说,现在所需的存储空间缩减为递归堆栈的大小,即存储空间的平均大小与lgn成正比。
虽然在实际的程序中,数组的下标(l和u)是非常重要的,但在这个框架版本中并不重要。因此,我们可以用一个表示子数组大小的整数(n)来替代这两个下标(参见示例2-5)
【示例2-5】 在Quicksort代码框架中使用一个表示子数组大小的参数
void qc(int n)
{ int m;
if (n <= 1) return;
m = randint(1, n);
comps += n-1;
qc(m-1);
qc(n-m);
}
现在,我们可以很自然地把这个过程整理为一个统计比较次数的函数,这个函数将返回在随机Quicksort算法中的比较次数。在示例2-6中给出了这个函数。
【示例2-6】 将Quicksort框架实现为一个函数
int cc(int n)
{ int m;
if (n <= 1) return 0;
m = randint(1, n);
return n-1 + cc(m-1) + cc(n-m);
}
在示例2-4、示例2-5和示例2-6中解决的都是相同的基本问题,并且所需的都是相同的运行时间和存储空间。在后面的每个示例都对这些函数的形式进行了改进,从而比这些函数更为清晰和简洁。
在定义发明家的矛盾(inventor's paradox)(How To Solve It, Princeton University Press)时,George Póllya指出“计划越宏大,成功的可能性就越大。”现在,我们就来研究在分析Quicksort时的矛盾。到目前为止,我们遇到的问题是,“当Quicksort对大小为n的数组进行一次排序时,需要进行多少次比较?”我们现在将对这个问题进行扩展,“对于大小为n的随机数组来说,Quichsort算法平均需要进行多少次的比较?”我们通过对示例2-6进行扩展以引出示例2-7。
【示例2-7】 伪码:Quicksort的平均比较次数
float c(int n)
if (n <= 1) return 0
sum = 0
for (m = 1; m <= n; m++)
sum += n-1 + c(m-1) + c(n-m)
return sum/n
如果在输入的数组中最多只有一个元素,那么Quichsort将不会进行比较,如示例2-6
13
中所示。对于更大的n,这段代码将考虑每个划分值m(从第一个元素到最后一个,每个都是等可能的)并且确定在这个元素的位置上进行划分的运行开销。然后,这段代码将统计这些开销的总和(这样就递归地解决了一个大小为m-1的问题和一个大小为n-m的问题),然后将总和除以n得到平均值并返回这个结果。
如果我们能够计算这个数值,那么将使我们实验的功能更加强大。我们现在无需对一个n值运行多次来估计平均值,而只需一个简单的实验便可以得到真实的平均值。不幸的是,实现这个功能是要付出代价的:这个程序的运行时间正比于3n(如果是自行参考(self-referential)的,那么用本章中给出的技术来分析运行时间将是一个很有趣的练习)。
示例2-7中的代码需要一定的时间开销,因为它重复计算了中间结果。当在程序中出现这种情况时,我们通常会使用动态编程来存储中间结果,从而避免重复计算。因此,我们将定义一个表t[N+1],其中在t[n]中存储c[n],并且按照升序来计算它的值。我们将用N来表示n的最大值,也就是进行排序的数组的大小。在示例2-8中给出了修改后的代码。
【示例2-8】 在Quicksort中使用动态编程来计算
t[0] = 0
for (n = 1; n <= N; n++)
sum = 0
for (i = 1; i <= n; i++)
sum += n-1 + t[i-1] + t[n-i]
t[n] = sum/n
这个程序只对示例2-7进行了细微的修改,即用t[n]来替换c(n)。它的运行时间将正比于N2,并且所需的存储空间正比于N。这个程序的优点之一就是:在程序执行结束时,数组t中将包含数组中从元素0到元素N的真实平均值(而不是样本均值的估计)。我们可以对这些值进行分析,从而生成在Quichsort算法中统计比较次数的计算公式。
我们现在来对程序做进一步的简化。第一步就是把n-1移到循环的外面,如示例2-9所示。
【示例2-9】 在Quicksort中把代码移到循环外面来计算
t[0] = 0
for (n = 1; n <= N; n++)
sum = 0
for (i = 1; i <= n; i++)
sum += t[i-1] + t[n-i]
t[n] = n-1 + sum/n
现在将利用对称性来对循环做进一步的调整。例如,当n为4时,内部循环计算总和为:
t[0]+t[3] + t[1]+t[2] + t[2]+t[1] + t[3]+t[0]
在上面这些组对中,第一个元素增加而第二个元素减少。因此,我们可以把总和改写为:
2 * (t[0] + t[1] + t[2] + t[3])
我们可以利用这种对称性来得到示例2-10中的Quicksort。
【示例2-10】 在Quichsort中利用了对称性来计算
t[0] = 0
14
for (n = 1; n <= N; n++)
sum = 0
for (i = 0; i < n; i++)
sum += 2 * t[i]
t[n] = n-1 + sum/n
然而,在这段代码的运行时间中同样存在着浪费,因为它重复地计算了相同的总和。此时,我们不是把前面所有的元素加在一起,而是在循环外部初始化总和并且加上下一个元素,如示例2-11所示。
【示例2-11】 在Quicksort中删除了内部循环来计算
sum = 0; t[0] = 0
for (n = 1; n <= N; n++)
sum += 2*t[n-1]
t[n] = n-1 + sum/n
这个小程序确实很有用。程序的运行时间与N成正比,对于每个从1到N的整数,程序将生成一张Quicksort的估计运行时间表。
我们可以很容易地把示例2-11用表格来实现,其中的值可以立即用于进一步的分析。在2-1给出了最初的结果行。
表2-1 示例2-11中实现的表格输出
N Sum t[n]
0 0 0
1 0 0
2 0 1
3 2 2.667
4 7.333 4.833
5 17 7.4
6 31.8 10.3
7 52.4 13.486
8 79.371 16.921
这张表中的第一行数字是用代码中的三个常量来进行初始化的。下一行(输出的第三行)的数值是通过以下公式来计算的:
A3 = A2+1 B3 = B2 + 2*C2 C3 = A2-1 + B3/A3
把这些(相应的)公式记录下来就使得这张表格变得完整了。这张表格是“我曾经编写的最漂亮代码”的很好的证据,即使用少量的代码完成大量的工作。
但是,如果我们不需要所有的值,那么情况将会是什么样?如果我们更希望通过这种来方式分析一部分数值(例如,在20到232之间所有2的指数值)呢?虽然在示例2-11中构建了完整的表格t,但它只需要使用表格中的最新值。因此,我们可以用变量t的定长空间来替代table t[]的线性空间,如示例2-12所示。
【示例2-12】 Quicksoft 计算——最终版本
sum = 0; t = 0
15
for (n = 1; n <= N; n++)
sum += 2*t
t = n-1 + sum/n
然后,我们可以插入一行代码来测试n的适应性,并且在必要时输出这些结果。
这个程序是我们漫长学习旅途的终点。通过本章所采用的方式,我们可以证明Alan Perlis的经验是正确的:“简单性并不是在复杂性之前,而是在复杂性之后” ("Epigrams on Programming," Sigplan Notices, Vol. 17, Issue 9)。

经典排序之冒泡排序



简述各种排序算法的优缺点~

  一、冒泡排序
  已知一组无序数据a[1]、a[2]、……a[n],需将其按升序排列。首先比较a[1]与 a[2]的值,若a[1]大于a[2]则交换 两者的值,否则不变。再比较a[2]与a[3]的值,若a[2]大于a[3]则交换两者的值,否则不变。再比 较a[3]与a[4],以此 类推,最后比较a[n-1]与a[n]的值。这样处理一轮后,a[n]的值一定是这组数据中最大的。再对a[1]~a[n- 1]以相同方法 处理一轮,则a[n-1]的值一定是a[1]~a[n-1]中最大的。再对a[1]~a[n-2]以相同方法处理一轮,以此类推。共处理 n-1 轮 后a[1]、a[2]、……a[n]就以升序排列了。
  优点:稳定;
  缺点:慢,每次只能移动相邻两个数据。

  二、选择排序
  每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数 据元素排完。
  选择排序是不稳定的排序方法。
  n 个记录的文件的直接选择排序可经过n-1 趟直接选择排序得到有序结果:
  ①初始状态:无序区为R[1..n],有序区为空。
  ②第1 趟排序 在无序区R[1..n]中选出关键字最小的记录R[k],将它与无序区的第1 个记录R[1]交换,使R[1..1]和R[2..n]分别变 为记录个数增加1 个的新有序区和记录个数减少1 个的新无序区。
  ③第i 趟排序
  第i 趟排序开始时,当前有序区和无序区分别为R[1..i-1]和R(1≤i≤n-1)。该趟 排序从当前无序区中选出关键字最 小的记录 R[k],将它与无序区的第1 个记录R 交换,使R[1..i]和R 分别变为记录个数增加1 个的新有序区和记录个数减少 1 个的新无序区。
  这样,n 个记录的文件的直接选择排序可经过n-1 趟直接选择排序得到有序结果。
  优点:移动数据的次数已知(n-1 次);
  缺点:比较次数多。

  三、插入排序
  已知一组升序排列数据a[1]、a[2]、……a[n],一组无序数据b[1]、 b[2]、……b[m],需将二者合并成一个升序数列。 首先比较b[1]与a[1]的值,若b[1]大于a[1],则跳过,比较b[1]与a[2]的值, 若b[1]仍然大于a[2],则继续跳过,直 到b[1]小于a 数组中某一数据a[x],则将a[x]~a[n]分别向后移动一位,将b[1]插入到原来 a[x]的位置这就完成了b[1] 的插入。b[2]~b[m]用相同方法插入。(若无数组a,可将b[1]当作n=1 的数组a)
  优点:稳定,快;
  缺点:比较次数不一定,比较次数越少,插入点后的数据移动越多,特别是当数据总量庞大的时候,但用链表可以解决 这个问题。

  四、缩小增量排序
  由希尔在1959 年提出,又称希尔排序(shell 排序)。
  已知一组无序数据a[1]、a[2]、……a[n],需将其按升序排列。发现当n 不大时,插入 排序的效果很好。首先取一增 量d(d<n),将a[1]、a[1+d]、a[1+2d]……列为第一组,a[2]、a[2+d]、 a[2+2d]……列为第二组……,a[d]、a[2d]、a[3d]……="" 列为最后一组以次类推,在各组内用插入排序,然后取d'<d,重复上述操="" 作,直到d="1。"
  优点:快,数据移动少;=""
  缺点:不稳定,d="" 的取值是多少,应取多少个不同的值,都无法确切知道,只能凭经验来取。=""

  五、快速排序=""
  快速排序是冒泡排序的改进版,是目前已知的最快的排序方法。
  ="" 已知一组无序数据a[1]、a[2]、……a[n],需将其按升序排列。首先任取数据a[x]="" 作为基准。比较a[x]与其它数据并="" 排序,使a[x]排在数据的第k="" 位,并且使a[1]~a[k-1]中的每一个数="" 据a[x],然后采 用分治的策略分别对a[1]~a[k-1]和a[k+1]~a[n] 两组数据进行快速排序。
  优点:极快,数据移动少;
  缺点:不稳定。

下面是我以前写的,希望对你有帮助。
#include
#include
#include
using namespace std;
#define N 100 //产生的数的个数

//冒泡排序

void Bubble_Sort(int R[],int n ){
char flag='0';
cout<<"是否输出所有的数字(1/0):"<<endl;
cin>>flag;
while(flag>'1'||flag<'0'){
cout<<"输入有误,请重新输入:"<<endl;
cin>>flag;
}
int i;
if(flag=='1'){
cout<<"排序前:"<<endl;
for( i=1;i<=n;i++)
cout<<R[i]<<',';
cout<<endl;
}
for(i=1;i<n;i++){ //执行n-1趟
int swap=0;
for(int j=1;j<=n-i;j++){

if(R[j] > R[j+1] ){
R[0]=R[j];
R[j]=R[j+1];
R[j+1]=R[0];

swap=1;
}
}
if(swap==0) // 没有发生一次交换,说明序列有序,则跳出循环,排序结束
break;
}
if(flag=='1'){
cout<<"冒泡排序后:"<<endl;
for(i=1;i<=n;i++)
cout<<R[i]<<',';
cout<<endl;
}

}

//快速排序
int Partition(int R[],int i,int j){ //已R[i]为支点进行划分,算法返回支点记录最终的位置
R[0]=R[i]; //缓存支点记录
while(i<j){ //从表的两端交替地向中间扫描
while(i=R[0])
j--;

if(i<j){ //将比支点记录小的交换到前面
R[i]=R[j];
i++;

}
while(i<j&&R[i]<R[0])
i++;

if(i<j){ //将比支点记录大的交换到后面
R[j]=R[i];
j--;
}
}
R[i]=R[0];

return i;
}
void Quick_Sort(int R[],int s,int t){
int i;
if(s<t){
i=Partition(R,s,t); //将表一分为二
Quick_Sort(R,s,i-1); //对支点前端子表递归排序
Quick_Sort(R,i+1,t); //对支点后端子表递归排序
}
}
void Quick(int R[],int n){
char flag='0';
cout<<"是否输出所有的数字(1/0):"<<endl;
cin>>flag;
while(flag>'1'||flag<'0'){
cout<<"输入有误,请重新输入:"<<endl;
cin>>flag;
}
int i;
if(flag=='1'){
cout<<"排序前:"<<endl;
for(i=1;i<=n;i++)
cout<<R[i]<<',';
cout<<endl;
}

Quick_Sort(R,1,n);

if(flag=='1'){
cout<<"快速排序后:"<<endl;
for(i=1;i<=n;i++)
cout<<R[i]<<',';
cout<<endl;
}
}


int main(){
while(1){
int R[N+1],i;
cout<<"1 在完全随机的情况下对关键码进行排序"<<endl;
cout<<"2 在完全正序的情况下对关键码进行排序"<<endl;
cout<<"3 在完全逆序的情况下对关键码进行排序"<<endl;
cout<<"0 退出"<<endl;
cout<<"请选择:"<<endl;
char p;
cin>>p;
while(p-483){
cout<<"输入有误,请重新输入:"<<endl;
cin>>p;
}
if(p-48==0)
break;
if(p-48==1){
srand((unsigned)time(NULL));
for(i=1;i<=N;i++)
R[i]=rand()%10000+1;
}
else if(p-48==2){
for(i=1;i<=N;i++)
R[i]=i;
}
else
for(i=N;i>=1;i--)
R[N-i+1]=i;

char k;
cout<<endl;


cout<<"1 冒泡排序"<<endl;
cout<<"2 快速排序"<<endl;
cout<<"0 退出"<<endl;

cout<<"请选择排序方法:"<<endl;
cin>>k;
while(k-482){
cout<<"输入有误,请重新输入:"<<endl;
cin>>k;
}
switch(k-48){
case 0:cout<<"谢谢使用!"<<endl;exit(0);
case 1:Bubble_Sort(R,N);break;
case 2:Quick(R,N);break;
}
system("pause");system("cls");
}
return 0;
}

简述各种排序算法的优缺点
答:五、快速排序=""快速排序是冒泡排序的改进版,是目前已知的最快的排序方法。="" 已知一组无序数据a[1]、a[2]、……a[n],需将其按升序排列。首先任取数据a[x]="" 作为基准。比较a[x]与其它数据并="" 排序,使a[x]排在数据的第k="" 位,并且使a[1]~a[k-1]中的每一个数="" ...

快速排序法
答:快速排序由C. A. R. Hoare在1960年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。[1]中文名 快速排序算法 外文...

快速排序算法
答:重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。快速排序算法通过多次比较和交换来实现排序,其排序流程如下:(1)首先设定一个分界值,通过该分界值将数组分成左右两部分。(2)将大于或...

二级C语言排序技术2
答:回答:很简单,对于笔试,多看看书书,对照书本多做做模拟题。机试那你要多上机练练,不懂的地方找一个会C语言的人请教一下。辅导书用南开100题比较不错,祝你好运!计算机二级C语言笔试有:公共基础知识 二级C,上机有:程序填空 程序改错 程序编译(这三题主要是应用函数调用)A 公共基础知识基本要求1.掌握...

有什么好用的排序算法?
答:快速排序使用分治法策略来把一个串行(list)分为两个子串行(sub-lists)。算法二: 堆排序算法 堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序的平均时间复杂度为O(...

各种排序算法
答:线性对数阶 (O(nlog2n)) 排序 快速排序、堆排序和归并排序;O(n1+§)) 排序,§ 是介于 0 和 1 之间的常数。 希尔排序 线性阶 (O(n)) 排序 基数排序,此外还有桶、箱排序。关于稳定性 稳定的排序算法:冒泡排序、插入排序、归并排序和基数排序。不是稳定的排序算法:选择排序、快速排序、...

java怎么让数组的数字从大到小排序?
答:将数字从大到小排序的方法:例如简一点的冒泡排序,将第一个数字和后面的数字逐个比较大小,如果小于,则互换位置,大于则不动。此时,第一个数为数组中的最大数。然后再将第二个数与后面的数逐个比较,以次类推。示例代码如下: public class Test { public static void main(String[] args) { ...

稳定的排序算法有哪些
答:4、基数排序:基数排序是一种非比较排序算法,它根据数字的位数来对数据进行排序。它是稳定的,特别适合对数字进行排序。5、计数排序:计数排序是一种非比较排序算法,它通过统计每个元素出现的次数来对数据进行排序。计数排序是稳定的,但对数据的范围有一定要求。不稳定的排序算法 1、快速排序:快速排序...

快速排序算法原理与实现
答:快速排序的基本思想就是从一个数组中任意挑选一个元素(通常来说会选择最左边的元素)作为中轴元素,将剩下的元素以中轴元素作为比较的标准,将小于等于中轴元素的放到中轴元素的左边,将大于中轴元素的放到中轴元素的右边。然后以当前中轴元素的位置为界,将左半部分子数组和右半部分子数组看成两个新的...

八大经典排序算法原理及实现
答:归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。快速排序在应该是大家经常看到、听到的算法,但是真正默写出来是有难度的。希望大家看了下面 挖坑填数 方法后,能快速写出、快速排序。其原理就这么几句话,但是现实起来并不是这么简单,...