• java 快速排序 递归The function calls itself until someone stops it. 该函数将自行调用，直到有人停止它为止。 Recursion can feel difficult to new developers. Perhaps that's because many resources teach...

java 快速排序 递归
The function calls itself until someone stops it.
该函数将自行调用，直到有人停止它为止。
Recursion can feel difficult to new developers. Perhaps that's because many resources teach it using algorithmic examples (Fibonacci, linked-lists). This piece will hopefully introduce things plainly, using one simple example.
对于新开发人员而言，递归可能会感到困难。 也许是因为许多资源都使用算法示例(斐波纳契(Fibonacci)，链接列表)来教它。 希望通过一个简单的例子，这篇文章将简单地介绍一下。
核心思想 (Core Idea)
Recursion is when a function calls itself until someone stops it. If no one stops it then it'll recurse (call itself) forever.
递归是指函数调用自身直到有人停止它。 如果没有人停止，它将永远递归 (自称)。

Recursive functions let you perform a unit of work multiple times. This is exactly what for/while loops let us accomplish! Sometimes, however, recursive solutions are a more elegant approach to solving a problem.
递归函数使您可以多次执行一个工作单元。 这正是for/while循环让我们完成的！ 但是，有时递归解决方案是解决问题的一种更优雅的方法。
倒数功能 (Countdown Function)
Let's create a function that counts down from a given number. We'll use it like this.
让我们创建一个从给定数字开始倒数的函数。 我们将像这样使用它。
countDownFrom(5);
// 5
// 4
// 3
// 2
// 1
And here's our algorithm to solve this problem.
这是我们解决此问题的算法。
Take one parameter called number. This is our starting point. 取一个称为number参数。 这是我们的出发点。 Go from number down to 0, logging each one along the way. 从number降低到0 ，并沿途记录每个number 。
We'll start with a for loop approach and then compare it to a recursive one.
我们将从for循环方法开始，然后将其与递归方法进行比较。
命令式方法(循环) (Imperative approach (loops))
function countDownFrom(number) {
for (let i = number; i > 0; i--) {
console.log(i);
}
}

countDownFrom(5);
// 5
// 4
// 3
// 2
// 1
This one contains both algorithmic steps.
这包含两个算法步骤。
✅ Take one parameter called number. ✅取一个称为number参数。 ✅ Log everything from number to 0. ✅记录从number到0所有内容。
递归方法 (Recursive approach)
function countDownFrom(number) {
if (number === 0) {
return;
}

console.log(number);
countDownFrom(number - 1);
}

countDownFrom(5);
// 5
// 4
// 3
// 2
// 1
This one also passes.
这也过去了。
✅ Take one parameter called number. ✅取一个称为number参数。 ✅ Log everything from number to 0. ✅记录从number到0所有内容。
So conceptually the two approaches are the same. However, they get the job done in different ways.
因此，从概念上讲，这两种方法是相同的。 但是，他们以不同的方式完成工作。
调试我们的命令性解决方案 (Debugging our imperative solution)
For a more visual example, let's put a debugger in our loop version and throw it into Chrome Developer Tools.
对于更直观的示例，让我们在循环版本中放入debugger ，然后将其放入Chrome开发者工具中。
function countDownFrom(number) {
for (let i = number; i > 0; i--) {
console.log(i);
debugger;
}
}

See how it uses an extra variable, i, to track the current number? As you iterate i decreases, eventually hitting 0 and terminating.
看看它如何使用额外的变量i来跟踪当前数字吗？ 随着您的迭代， i逐渐减少，最终达到0并终止。
And in the for loop we specified "stop if i > 0".
在for循环中，我们指定“如果i > 0停止”。
调试我们的递归解决方案 (Debugging our recursive solution)
function countDownFrom(number) {
if (number === 0) {
return;
}

console.log(number);

debugger;

countDownFrom(number - 1);
}

The recursive version doesn't need extra variables to track its progress. Notice how the pile of functions (call stack) grows as we recurse?
递归版本不需要额外的变量来跟踪其进度。 注意我们递归时函数堆( 调用堆栈 )如何增长？
That's because each call to countDownFrom adds to the stack, feeding it number - 1. By doing this we're we're passing along an updated number each time. No extra state needed!
这是因为对countDownFrom的每次调用countDownFrom添加到堆栈中，并向其提供number - 1 。 通过这样做，我们每次都传递一个更新的number 。 不需要额外的状态！
That's main difference between the two approaches.
这是两种方法之间的主要区别。
Iterative uses internal state (extra variables for counting, etc). 迭代使用内部状态(用于计数的其他变量等)。 Recursive does not, it simply passes updated parameters between each call. 递归没有，它只是在每次调用之间传递更新的参数。
But how does either version know when to stop?
但是，哪个版本知道何时停止？
无限循环 (Infinite Loops)
在旅行中，您可能已经被警告过可怕的无限循环。
🚨 THIS RUNS FOREVER, BE WARNED 🚨
while (true) { console.log('WHY DID YOU RUN THIS?!' }

🚨 THIS RUNS FOREVER, BE WARNED 🚨
for (i = 0;;) { console.log('WHY DID YOU RUN THIS?!') }
Since they'd theoretically run forever, an infinite loop will halt your program and possibly crash your browser. You can prevent them by always coding a stopping condition.
由于理论上它们将永远运行，因此无限循环将暂停您的程序，并可能导致浏览器崩溃。 您可以通过始终编写停止条件来防止它们发生。
✅ This does not run forever
x = 0;
while (x < 3) { console.log(x); x++; }

✅ This does not run forever
for (x = 0; x < 3; x++) { console.log(x); }
In both cases we log x, increment it, and stop when it becomes 3. Our countDownFrom function had similar logic.
在这两种情况下，我们都记录x ，递增x ，然后在x变为3时停止。 我们的countDownFrom函数具有类似的逻辑。
// Stop at 0
for (let i = number; i > 0; i--)
Again, loops need extra state to determine when they should stop. That's what x and i are for.
同样，循环需要额外的状态来确定何时停止。 这就是x和i是。
无限递归 (Infinite Recursion)
Recursion also presents the same danger. It's not hard to write a self-referencing function that'll crash your browser.
递归也存在同样的危险。 编写会导致浏览器崩溃的自引用功能并不难。
🚨THIS RUNS FOREVER, BE WARNED🚨
function run() {
console.log('running');
run();
}

run();
// running
// running
// ...

Without a stopping condition, run will forever call itself. You can fix that with an if statement.
在没有停止条件的情况下， run将永远自我调用。 您可以使用if语句解决该问题。
✅ This does not run forever

function run(x) {
if (x === 3) return;

console.log('running');
run(x + 1);
}

run(0);
// running
// running
// running

// x is 3 now, we're done.
基本情况 (Base case)
This is known as the base case–our recursive countDownFrom had one.
这被称为基本案例–我们的递归countDownFrom有一个。
if (number === 0) {
return;
}
It's the same idea as our loop's stopping logic. Whichever approach you pick, always remember that at some point it needs to be stopped.
这与循环的停止逻辑相同。 无论选择哪种方法，请始终记住，必须在某个时候停止它 。

摘要 (Summary)
Recursion is when a function calls itself until someone stops it. 递归是一个函数调用自身直到有人停止它的时间。 It can be used instead of a loop. 可以使用它代替循环。 If no one stops it, it'll recurse forever and crash your program. 如果没有人停止它，它将永远递归并崩溃您的程序。 A base case is a condition that stops the recursion. Don't forget to add them! 基本情况是停止递归的条件。 不要忘记添加它们！ Loops use extra state variables for tracking and counting, while recursion only uses the provided parameters. 循环使用额外的状态变量进行跟踪和计数，而递归仅使用提供的参数。

For more content like this, check out https://yazeedb.com. And please let me know what else you'd like to see! My DMs are open on Twitter.
Until next time!
直到下一次！

翻译自: https://www.freecodecamp.org/news/quick-intro-to-recursion/

java 快速排序 递归

展开全文
• 快速排序 对冒泡排序的一种改进，若初始记录序列按关键字有序或基本有序，蜕化为冒泡排序。使用的是递归原理，在所有同数量级O(n longn) 的排序方法中，其平均性能最好。就平均时间而言，是目前被认为最好的一种内部...
• JAVA实现快速排序算法（递归快速排序是对冒泡排序的一种改进，它的基本思想是：选取数组中的第一个元素作为中间值，以中间值为基准，通过一趟排序后将要排序的数据分为两部分，左边部分的数值全部小于中间值，...
JAVA实现快速排序算法（递归）
快速排序是对冒泡排序的一种改进，它的基本思想是：选取数组中的第一个元素作为中间值，以中间值为基准，通过一趟排序后将要排序的数据分为两部分，左边部分的数值全部小于中间值，右边部分的数值全部大于中间值。然后再按照此方法对这两部分的数据再分别进行排序。整个排序过程可以递归进行。 实现效果如下： 排序前： 52 15 64 87 18  第1次排序后的结果: 18 15 52 87 64  第2次排序后的结果: 15 18 52 87 64  第3次排序后的结果: 15 18 52 87 64  第4次排序后的结果: 15 18 52 64 87 实现代码的思路是： (1) 设置两个变量left=0,right=arr.length-1; (2) 将数组的第一个元素作为中间值temp; (3) 从右向左开始寻找小于中间值的元素，若未找到则right递减，找到后将此数据的值赋给arr[left]（即arr[0]），然后left++;arr[0]的数据存于temp中所以不会有数据丢失 (4) 之后再从左向右查找大于中间值的元素，原理同上； (5) 直到left==right结束循环,将中间值赋给left或right；之后再使用递归方式对两部分数据再分别排序 实现代码如下：
public class QuickSort {
static int count = 0;
public static void main(String[] args) {
int[] arr = {52,15,64,87,18};
System.out.println("排序前：");
for (int i : arr) {
System.out.print(i+"\t");
}
System.out.println();
quicksort(0,arr.length-1,arr);
}
public static void quicksort(int l,int r,int[] arr){
count++;
//调用排序方法
int mid = Sort(l,r,arr);
//递归排序一轮排序后左半边数组
if(l<mid){
quicksort(l,mid-1,arr);
}
//递归排序一轮排序后右半边数组
if(r>mid){
quicksort(mid+1,r,arr);
}
}
public static int Sort(int left,int right,int[] arr){
int temp = arr[left];
while(left<right){
//从右向左查找小于中间值的元素
while(arr[right]>=temp&&left<right){
right--;
}
//找到之后把小的数值放在左边
arr[left]=arr[right];
left++;
//从左往右再查找大于中间值的元素
while(arr[left]<=temp&&left<right){
left++;
}
//找到之后把大的值存放在右边
arr[right]=arr[left];
}
//一轮排序结束
//把临时变量赋给中间值
arr[right]=temp;
System.out.println("第"+count+"次排序后的结果:");
for (int i : arr) {
System.out.print(i+"\t");
}
System.out.println();
return right;
}
}

展开全文
• Java递归方式实现快速排序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 ...


Java非递归方式实现快速排序

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

package
sort.algorithm;

import
java.util.Stack;

//快速排序的非递归实现，利用系统的栈stack

public
class
QuickSortNonRecursion {

     
public
static
void
main(String[] args) {

         
QuickSortNonRecursion qsnr = 
new
QuickSortNonRecursion();

         
int
[] array = {
0
, 
2
, 
11
, 
121
, 
18
, 
99
, 
3
, 
5
, 
101
, 
22
, 
9
, 
100
};

         
qsnr.quicksort(array);

          
for
(
int
i : array) {

                
System.out.print(i + 
"  "
);

          
}

        
}

                

        
public
void
quicksort(
int
[] array) {

            
if
(array == 
null
|| array.length == 
1
) 
return
;

            
//存放开始与结束索引

            
Stack<Integer> s = 
new
Stack<Integer>(); 

            
//压栈       

            
s.push(
0
); 

            
s.push(array.length - 
1
); 

            
//利用循环里实现

            
while
(!s.empty()) { 

                
int
right = s.pop(); 

                
int
left = s.pop(); 

                
//如果最大索引小于等于左边索引，说明结束了

                
if
(right <= left) 
continue
; 

                        

                
int
i = partition(array, left, right); 

                
if
(left < i - 
1
) {

                    
s.push(left);

                    
s.push(i - 
1
);

                
} 

                
if
(i + 
1
< right) {

                    
s.push(i+
1
);

                    
s.push(right);

                
}

            
} 

        
}

        
//找到轴心，进行交换

        
public
int
partition (
int
[] data, 
int
first, 
int
end)

        
{

            
int
temp;

            
int
i=first,j=end;

            
if
(first<end)

            
{

                
temp=data[i];

                
//当i=j的时候，则说明扫描完成了

                
while
(i<j)

                
{

                    
//从右边向左边扫描找到一个小于temp的元素

                    
while
(j>i&&data[j]>temp)j--;

                    
if
(i<j)

                    
{

                        
//将该元素赋值给temp

                        
data[i]=data[j];

                        
//赋值后就应该将i+1指向下一个序号

                        
i++;

                    
}

                          

                    
//然后从左边向右边开始扫描，找到一个大于temp的元素

                    
while
(i<j&&temp>data[i])i++;

                    
if
(i<j)

                    
{

                        
//将该元素赋值给temp

                        
data[j]=data[i];

                        
//赋值后就应该将j-1指向前一个序号

                        
j--;

                    
}

                
}

                
//将轴数据放在i位置中

                
data[i]=temp;

            
}

            
return
i;

        
}

    
}

本文转自 zhao_xiao_long 51CTO博客，原文链接:http://blog.51cto.com/computerdragon/1305987


展开全文
• 一、算法思想——分治而为 1、【二分】在待排数据中找一个锚点（或者分治点）...要达到在数组或列表中把数据分成两部分，我们使用两个“指针”完成数据检查和交换。我们叫它【双指针交换法】 （假设锚点是索引为0处.
一、算法思想——分治而为
1、【二分】在待排数据中找一个锚点（或者分治点），一般去第一个数据即可。把剩余的数据，与该锚点比较，小于锚点的排在锚点前面，大于等于锚点的排在锚点后面。
2、【递归】经过第一步，已经把数据分成了除锚点外的两部分：锚点前的部分小于锚点；锚点后的部分大于等于锚点。应用递归思想，把这两部分分别看做两个待排数组，分别应用快排算法。

二、如何“二分”
要达到在数组或列表中把数据分成两部分，我们使用两个“指针”完成数据检查和交换。我们叫它【双指针交换法】
（假设锚点是索引为0处的数据值，并复制锚点命名为mid，锚点处位置变成一个空位）
1、设置两个指针 left 和 right 。
2、right从数组尾部开始检查数据，若数据大于等于锚点mid，则继续检查前一个数据，直到找到一个小于锚点mid的数据或者left>=right；
3、把right位置处的数据拷贝到空位位置上。此时right位置变成一个新的空位。
4、left负责从数组头部开始检查数据，若数据小于锚点mid，则继续检查下一个数据，直到找到一个不小于锚点mid的数据或者left>=right；
5、把left位置处的数据拷贝到空位位置上。此时left位置变成一个新的空位。
6、【循环】让left和right指针继续从原来位置向下查找数据，直到left>=right，跳出循环，把mid赋值给最后剩余的空位即可。
这样数据就会变成这样：[小于mid的数据][mid][大于等于mid的数据]

三、快速排序代码
    /**
* 快速排序法（递归）
* @param arr 待排数组
* @param startPos 数组排序区域左端点索引
* @param endPos 数组排序区域右端点索引
*/
private void quickSort(int[] arr,int startPos, int endPos){
if(startPos >= endPos){
return;
}
int leftIndex = startPos;
int rightIndex = endPos;
int mid = arr[leftIndex]; //复制后，leftIndex变成空位
while (leftIndex < rightIndex){
//从右侧寻找小于mid的值
while (leftIndex < rightIndex && arr[rightIndex] >= mid){
rightIndex--;
}
arr[leftIndex] = arr[rightIndex]; //把找到的值放在前面的空位，rightIndex位置产生一个新的空位
//从左侧寻找大于等于mid的值
while (leftIndex < rightIndex && arr[leftIndex] < mid){
leftIndex++;
}
arr[rightIndex] = arr[leftIndex]; //把找到的值放在后面的空位，leftIndex位置产生一个新的空位
}
arr[leftIndex] = mid; //把中间值mid放在最后的空位上
quickSort(arr, startPos, leftIndex-1); //对左侧部分进行递归
quickSort(arr, leftIndex+1, endPos); //对右侧部分进行递归

}


展开全文
• 它的基本思想是：通过一趟排序将要排序的数据分割成独立的两部分，其中一部分的所有数据都比另外一部分的所有数据都要小，然后再按此方法对这两部分数据分别进行快速排序，整个排序过程可以递归进行，以此达到整个...
• 快速排序 的原理及其java实现（递归与非递归
• 以前学习数据结构的时候快排的循环都是双重for循环，今天偶尔看到了运用递归来实现快速排序，所以突发想记录一下。由于我以前学过c和java,现在在自学python，所以一下代码均为python。但基本思想是一样的。 1....
• 使用递归实现快速排序(Java实现) 1.先确定一个key值（也就是参考值），初状态定义如下 2.实现key的左边都是小于key的值，右边都是大于key的值 int key = arr[start];//防止访问溢出 while(start &amp;lt; end...
• java 快速排序 折半查找的界面实现 （递归与分治法）
• 问题当数据量较大时（数组长度1000000），快速排序递归算法栈溢出，且实际运行时间也比其他算法长，我猜测是由于大量的函数调用。有人能分析一下吗？如何改进？递归private void quick_sort_recursive(int head, int...
• 快速排序Java版） 听名字就很diao，直接上干货。（杠精别打我，支点的英文是pivot，我全拼错了） 快排一定要思路清晰，没事多几遍，要不容易忘。 对于一个数组对它进行排序，快排的思想就是交换交换再交换，我们...
• 两种方法： 传统的递归快速排序 采用非递归堆栈模拟
• 快速排序算法 工作之前一直不懂快速排序算法，今天看了下快速排序算法，跟大家分享下，如果有不妥之处还请建议。 快速排序是对冒泡排序的一种改进，由C.R.A.Hoare于1962年提出，它采用了一种分治的策略，通常称...
• 快速排序是大多数公司面试人员的必考题，今天将自己参考别人的思想所的两种快速排序的方式； 快速排序使用场景：无序列表，时间复杂度为O(log2N)； 快速排序的思想： 3.1、在一个数组中选取一个基准数，根据这...
• 快速排序的思想 ：一个数组 例如 int a[]={5,4,3,2,1} 实现从小到大排列 :首先选取一个关键值 我们取第一个数为关键值，在这里我简称K值 K值=5  5 4 6
• 因为排序思想是把数往两边扔，所以左右两边的数大小与key的关系相反*/ { i++; } a[j] = a[i]; } a[i] = key;/*当在当组内找完一遍以后就把中间数key回归*/ sort(a, left, i - 1);/*最后同样...
• /** * 递归分治算法学习之随机快速排序 * 采用随机选择枢纽元素的快速排序算法 * @author Sking */package 递归分治;import java.util.Random;pub
• 递归的注意事项二、快速排序1.快速排序概述2.快速排序实例 一、递归 1.递归的介绍 以编程的角度来看，递归指的是方法定义中调用方法本身的现象 把一个复杂的问题层层转化为一个与原问题相似的规模较小的问题来...
• 注：快速排序里需要操作很多集合，如果使用数组将会使代码变得难以理解和复杂，因为数组长是固定不可变的，但是我们却需要一个长度最好不固定的集合。既然java有list这个对需要频繁操作集合超级友好的类，干嘛不用它...
• 最近想探究一下算法方面的问题，闲着无聊就撸了一波快排的代码，以前都是直接拿过来的，但是想想毕竟那是别人的东西，只有自己学会才算自己的，思路其实不难，只是需要好的处理一些细节问题，下面来说说思路和代码...
• 我们对Markdown编辑器进行了一些功能拓展与语法支持，除了标准的Markdown编辑器功能，我们增加了如下几点新功能，帮助你博客： 全新的界面设计 ，将会带来全新的写作体验； 在创作中心设置你喜爱的代码高亮...
• 算法思想： ​ 在数组中选出一个元素做枢轴，把所有比它小的元素移...排序过程： 递归版： import java.util.Arrays; public class QuickSort { public static void main(String[] args) { int a[] = new in...
• 文章目录1. 基本思想2. 代码实现2.1 递归实现2.2 优化—非递归实现3. 性能分析 1. 基本思想 在数列排序中，如果只有一个数，那么它本身就是有序的；如果只有两个数，那么一次... 快速排序多种递归、非递归实现及性能
• 将已知数组进行排序 代码如下： public class MethodDemo15 { public static void main(String[] args) { //创建数组 int[] arr = {9, 8, 7, 6, 5, 4, 3, 2, 1}; //排序 quickSort(arr, 0, arr.length - 1); ...
• JAVA递归快排import java.util.Stack; public class Text { public static void main(String []args){ int[] a={10,8,4,5,3,1,2}; quickSort(a); } static void quickSort(int[] a){
• import java.net.PasswordAuthentication; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Stack; public class quickSort2 { public static void q...
• 挖坑法递归 void quicksort(int s[],int left,int right){ if(left<right){ int temp,i=left,j=right; temp=s[right]; while(i<j){ //...
• * 快速排序 * */ public class QuickSort{ /** * 递归一 * */ public static void sort1(int[] arr, int start, int end) { if(start ){ //初始先将第一个值 int pvoit = arr[start]; int ...

...

java 订阅