69 快速排序的递归和非递归实现

【本文链接】

http://www.cnblogs.com/hellogiser/p/quicksort-recursively-and-non-recursively.html

【代码】

C++ Code


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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
 
// 69_QuickSort_NonRecursive.cpp : Defines the entry point for the console application.
//
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/9/18
*/

#include "stdafx.h"
#include "iostream"
#include <ctime>
#include <algorithm>
#include <stack>
using namespace std;

void myswap(int &a, int &b)
{
    int t = a;
    a = b;
    b = t;
}

void print(int *a, int n)
{
    for (int i = 0; i < n; i++)
    {
        cout << a[i] << " ";
    }
    cout << endl;
}

//========================================================
//   recursively
//========================================================
int partition1(int *a, int left, int right)
{
    // a[left,...p-1]<=a[p]<a[p+1,...right]
    int i = left;
    int j = right;
    int key = a[left];
    while(i < j)
    {
        while(a[i] <= key) i++;
        while(a[j] > key) j--;
        if (i < j)
        {
            myswap(a[i], a[j]);
        }
    }
    // left---j---i---right
    myswap(a[left], a[j]);
    return j;
}

int partition2(int *a, int left, int right)
{
    // left, a[left+1...i]<=key, a[i+1,...j-1]>key
    int i = left;
    int j = left + 1;
    int key = a[left];
    while(j <= right)
    {
        if (a[j] < key)
        {
            i++;  // so that  a[i]>=key
            myswap(a[i], a[j]);
        }
        j++;
    }
    //left---i---right---j
    myswap(a[left], a[i]);
    return i;
}

void quicksort_r(int *a, int left, int right)
{
    if (left < right)
    {
        int p = partition1(a, left, right);
        quicksort_r(a, left, p - 1);
        quicksort_r(a, p + 1, right);
    }
}

void QuickSort_Recursively(int *a, int n)
{
    if (a == NULL || n <= 1)
        return;
    quicksort_r(a, 0, n - 1);
}

//========================================================
//  non recursively
//========================================================
void quicksort_non_r(int *a, int left, int right)
{
    // view [left,right] range as a node, which then has 2 child nodes [left,p-1] and [p+1,right] after partitioning
    if (left >= right)
        return;
    // init stack with one range node
    stack<int> s;
    s.push(left);
    s.push(right);
    int temp_right, temp_left;
    int p;
    while(!s.empty())
    {
        temp_right = s.top();
        s.pop();
        temp_left = s.top();
        s.pop();
        if (temp_left < temp_right)
        {
            p = partition1(a, temp_left, temp_right);
            // add node [left,p-1] and [p+1,right] to stack
            s.push(temp_left);
            s.push(p - 1);

s.push(p + 1);
            s.push(temp_right);
        }
    }
}

void QuickSort_NonRecursively(int *a, int n)
{
    if (a == NULL || n <= 1)
        return;
    quicksort_non_r(a, 0, n - 1);
}

typedef void (*fun)(int *a, int n);
void test_base(int *a, int n, fun f)
{
    print(a, n);
    f(a, n);
    print(a, n);
    cout << "==============================\n";
}

void test_recursively()
{
    srand((unsigned int)time(NULL));
    const int n = 10;
    int a[n];
    for (int i = 0; i < n; i++)
    {
        a[i] = rand() % 100;
    }
    cout << "recursively..." << endl;
    test_base(a, n, QuickSort_Recursively);
}

void test_non_recursively()
{
    srand((unsigned int)time(NULL));
    const int n = 20;
    int a[n];
    for (int i = 0; i < n; i++)
    {
        a[i] = rand() % 100;
    }
    cout << "non recursively..." << endl;
    test_base(a, n, QuickSort_NonRecursively);
}

void test_main()
{
    test_recursively();
    test_non_recursively();
}

int _tmain(int argc, _TCHAR *argv[])
{
    test_main();
    return 0;
}

/*
recursively...
43 5 68 83 74 12 80 61 84 48
5 12 43 48 61 68 74 80 83 84
==============================
non recursively...
43 5 68 83 74 12 80 61 84 48 67 95 57 2 17 17 98 94 17 76
2 5 12 17 17 17 43 48 57 61 67 68 74 76 80 83 84 94 95 98
==============================
*/

时间: 2024-11-10 07:51:37

69 快速排序的递归和非递归实现的相关文章

每天刷个算法题20160525:快速排序的递归转非递归解法

版权所有.所有权利保留. 欢迎转载,转载时请注明出处: http://blog.csdn.net/xiaofei_it/article/details/51524798 为了防止思维僵化,每天刷个算法题.已经刷了几天了,现在发点代码. 我已经建了一个开源项目,每天的题目都在里面: https://github.com/Xiaofei-it/Algorithms 绝大部分算法都是我自己写的,没有参考网上通用代码.读者可能会觉得有的代码晦涩难懂,因为那是我自己的理解. 最近几天都是在写一些原来的东西

算法之归并排序的递归与非递归的实现

一.什么是归并排序 归并排序就是将多个有序的数据段合成一个有序的数据段,如果参与合并的只有两个有序的数据段,则称为二路归并.与快速排序和堆排序相比,其最大的特点是一种稳定的算法,算法的平均时间复杂度O(nlog2n). 二.归并排序的基本思路 (1).对于一个原始的待排序表,可以将R[1]到R[n]可以看做是n个长度为1的有序表,即分解. (2).进行第一趟归并,即将上述的n个子序两两合并,得到 n/2向上取整 个有序表,若n为奇数,则归并到最后一个子序列长度为1,即合并. (3).再将两个 n

树的递归与非递归遍历总结

树的递归遍历遍历很简单,非递归遍历要复杂一些,非递归先序.中序.后序遍历需要用一个辅助栈,而层次遍历则需要一个辅助队列. 树的结构: 1 public class Tree<T> { 2 private T data; 3 private Tree<T> left; 4 private Tree<T> right; 5 ... 6 } 用策略模式定义一个访问工具: 1 public interface Visitor<T> { 2 void process(

二叉树遍历算法总结(递归与非递归)

一:前言 二叉树的遍历方法分四种:前序,中序,后序以及层次遍历. 其中,前中后遍历方法的实现分递归和非递归,非递归遍历的实现需要借助于栈. 实际上,递归的调用就是一种栈的实现,所以,非递归遍历就需要人工借助栈结构来实现. 而层次遍历需要借助队列. 二:前中后序遍历 递归遍历: 递归遍历的思想和方法很简单,通过调整输出语句来实现前,中,后三种遍历. 代码如下: 1 void show(BiTree T) 2 { 3 if(T) 4 { 5 printf("%c ",T->data)

递归与非递归及其相互转换

一.什么是递归 递归是指某个函数直接或间接的调用自身.问题的求解过程就是划分成许多相同性质的子问题的求解,而小问题的求解过程可以很容易的求出,这些子问题的解就构成里原问题的解了. 二.递归的几个特点 1.递归式,就是如何将原问题划分成子问题. 2.递归出口,递归终止的条件,即最小子问题的求解,可以允许多个出口. 3.界函数,问题规模变化的函数,它保证递归的规模向出口条件靠拢 三.递归的运做机制 很明显,很多问题本身固有的性质就决定此类问题是递归定义,所以递归程序很直接算法程序结构清晰.思路明了.

[转] 树的递归与非递归遍历

1 public class Tree<T> { 2 private T data; 3 private Tree<T> left; 4 private Tree<T> right; 5 6 private Tree(T data) { 7 this.data = data; 8 9 } 10 11 public Tree(T[] datas) { 12 makeTree(datas, this); 13 } 14 15 public interface Visitor

C实现二叉树(模块化集成,遍历的递归与非递归实现)

C实现二叉树模块化集成 实验源码介绍(源代码的总体介绍):header.h : 头文件链栈,循环队列,二叉树的结构声明和相关函数的声明.LinkStack.c : 链栈的相关操作函数定义.Queue.c : 循环队列的相关操作函数定义.BinTree.c : 二叉树的相关操作的函数定义,层序序列生成二叉树,二叉树的前序序列.中序序列.后序序列的递归和非递归实现,求叶子结点的递归与非递归实现,求树高.我目前还是新手且第一次写类似的博客,文章中难免会有错误!如发现错误,望各路大神能够指出!详见源代码

二叉树的广度优先遍历、深度优先遍历的递归和非递归实现方式

二叉树的遍历方式: 1.深度优先:递归,非递归实现方式 1)先序遍历:先访问根节点,再依次访问左子树和右子树 2)中序遍历:先访问左子树,再访问根节点吗,最后访问右子树 3)后序遍历:先访问左子树,再访问右子树,最后访问根节点 2.广度优先     按照树的深度,一层一层的访问树的节点 1 package Solution; 2 3 import java.util.LinkedList; 4 import java.util.Queue; 5 import java.util.Stack; 6

数据结构二叉树的递归与非递归遍历之 实现可编译(1)java

前一段时间,学习数据结构的各种算法,概念不难理解,只是被C++的指针给弄的犯糊涂,于是用java,web,javascript,分别去实现数据结构的各种算法. 二叉树的遍历,本分享只是以二叉树中的先序遍历为例进行说明,中序遍历和后序遍历,以此类推! 二叉树递归与非递归遍历的区别,虽然递归遍历,跟容易读懂,代码量少,运算快,但是却容易出现溢出的问题,所以所以非递归遍历,在处理千万级的运算量时会先的很有用处. 二叉树的先序遍历:先访问根节点,再访问先后访问左右节点.如图: 二叉树的递归遍历之java

数据结构——二叉树遍历之“递归与非递归遍历”

简述 二叉树的遍历分为先序遍历.中序遍历和后序遍历.如下图所示: 递归遍历 private void bianli1(List<Integer> list, TreeNode root) { // 先序遍历 if (root == null) { return; } list.add(root.val); bianli1(list, root.left); bianli1(list, root.right); } private void bianli2(List<Integer>