| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2788 人关注过本帖
标题:有多少人写程序必须经常用到递归的?
只看楼主 加入收藏
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
收藏
得分:0 
以下是引用Devil_W在2010-7-29 18:39:33的发言:

 
 
没文化的人才这么说。
 
我写的递归比你不用递归说不定效率更高。
 
刚好我这里有个题目, 封装一个链表。 在O(N)的时间里面找到链表里面第k大的数。
 
哥用递归,你用非递归,看谁的效率高。
 
不是哥看不起你。你也许死都没办法做到O(n)的效率。
vs_inzaghi
我以一个菜鸟的口吻扯几句:
熟悉快速排序的话, 这道题目很简单,是一个基于 快速排序划分的选择问题,
快速排序(降序)重排  a[left].....a[right], 返回一个位置 i, 满足 a[left]...a[i-1] 都大于等于 a[i],
a[i+1]...a[right]都小于等于a[i]. 对于找第k大的数的问题, 如果 i 等于 k, 完成查找。如果 i < k; 查找
左子文件,如果 i > k, 查找右子文件。 平均时间复杂度为 0(n).
当然,这个问题 可以用 选择排序 或 其他的方法解答,效率要低一点。

我不觉得这个问题有必要用链表解答,如果是因为表现一下链式结构的操作能力,值得学习,否则的话,我只能说
you 是个废柴。
我也不觉得这个问题有必要用递归解答,这道题的 非递归解法,比递归解法 简单很多,也很容易理解。
如果是因为表现一下递归算法的能力,值得学习,否则的话,我只能说
you 是个废柴。

链表相聚对数组只是在 频繁的插入、删除时有优势。
看到 vs_inzaghi有这样一个观点, 认为 使用链表节省空间。 怎么会呢? 链表的一个节点起码有一个 自引用
指针,一个指针占 4 个字节,分配 1000个元素,就得比数组 多出 4000个字节,What a terrible thing 啊!
动态链表内存管理上要灵活一点,但是动态分配内存容易出错,你得为 什么时候分配,什么时候释放烦恼。
静态数据固化在内存中, 虽然比较死板, 却不容易出错。自动变量,虽容易溢出,但是也还是比较好用的。

选择 某种 数据结构 和 算法时,得分清场合,不合理的乱用,只会带来麻烦。我没有搞过嵌入式开发,不过
我可以断言一句, 嵌入式开发用到 链表 和 递归的 几率为 log1 .



[ 本帖最后由 BlueGuy 于 2010-7-31 12:45 编辑 ]

我就是真命天子,顺我者生,逆我者死!
2010-07-30 08:58
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
收藏
得分:0 
时间关系不扯那么多了。

我就是真命天子,顺我者生,逆我者死!
2010-07-30 08:58
Devil_W
Rank: 10Rank: 10Rank: 10
等 级:青峰侠
威 望:9
帖 子:1160
专家分:1797
注 册:2009-9-14
收藏
得分:0 
以下是引用BlueGuy在2010-7-30 08:58:06的发言:

vs_inzaghi
我以一个菜鸟的口吻扯几句:
熟悉快速排序的话, 这道题目很简单,是一个基于 快速排序划分的选择问题,
快速排序(降序)重排  a[left].....a[right], 返回一个位置 i, 满足 a[left]...a 都大于等于 a,
a...a[right]都小于等于a. 对于找第k大的数的问题, 如果 i 等于 k, 完成查找。如果 i > k; 查找
左子文件,如果 i < k, 查找右子文件。 平均时间复杂度为 0(n).
当然,这个问题 可以用 选择排序 或 其他的方法解答,效率要低一点。

我不觉得这个问题有必要用链表解答,如果是因为表现一下链式结构的操作能力,值得学习,否则的话,我只能说
you 是个废柴。
我也不觉得这个问题有必要用递归解答,这道题的 非递归解法,比递归解法 简单很多,也很容易理解。
如果是因为表现一下递归算法的能力,值得学习,否则的话,我只能说
you 是个废柴。

链表相聚对数组只是在 频繁的插入、删除时有优势。
看到 vs_inzaghi有这样一个观点, 认为 使用链表节省空间。 怎么会呢? 链表的一个节点起码有一个 自引用
指针,一个指针占 4 个字节,分配 1000个元素,就得比数组 多出 4000个字节,What a terrible thing 啊!
动态链表内存管理上要灵活一点,但是动态分配内存容易出错,你得为 什么时候分配,什么时候释放烦恼。
静态数据固化在内存中, 虽然比较死板, 却不容易出错。自动变量,虽容易溢出,但是也还是比较好用的。

选择 某种 数据结构 和 算法时,得分清场合,不合理的乱用,只会带来麻烦。我没有搞过嵌入式开发,不过
我可以断言一句, 嵌入式开发用到 链表 和 递归的 几率为 log1 .

你这个蠢货。

有种你把你的代码贴出来大家欣赏下。

我最鄙视不贴代码就知道TMD扯淡的垃圾。
2010-07-30 09:33
sunyh1999
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:14
帖 子:1178
专家分:3032
注 册:2009-5-17
收藏
得分:0 
递归有时确实会大大降低运行效率,但是有时在某个特定的问题上是很有用的

欢迎来到我的博客:http://blog..cn/noisunyuhong
2010-07-30 09:56
南国迦叶
Rank: 2
等 级:论坛游民
帖 子:46
专家分:20
注 册:2010-7-9
收藏
得分:0 
版主高手啊,致敬!
2010-07-30 10:39
hao0716
Rank: 4
等 级:业余侠客
威 望:1
帖 子:353
专家分:222
注 册:2006-4-11
收藏
得分:0 
选择 某种 数据结构 和 算法时,得分清场合,不合理的乱用,只会带来麻烦。我没有搞过嵌入式开发,不过
我可以断言一句, 嵌入式开发用到 链表 和 递归的 几率为 log1 .
--------------------------------------------------------------------------------------------------------------
嵌入式开发用到链表的机会太多了,递归倒是比较少
实际上分配大内存数组的方式不靠谱,因为嵌入式平台,比如vxworks是没有虚拟内存的,没办法swap

不过有些题目递归是容易解决的,主要是效率,还有内存的占用,感兴趣的话可以看看dancing link的算法,4向链表,效率很高,内存占用少

2010-07-30 10:52
xx342508809
Rank: 2
等 级:论坛游民
帖 子:89
专家分:51
注 册:2010-7-28
收藏
得分:0 
顶下,我也 觉的递归没循环好用~~~~~~~~~
2010-07-30 15:43
嗯_懒羊羊
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2010-7-30
收藏
得分:0 
个人觉得,在解决相对比较复杂的问题,递归要好。简单的问题,循环方便。
2010-07-30 16:05
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
收藏
得分:0 
回复 13楼 Devil_W
扔一份给你,
#include <stdio.h>

typedef int Item;
#define NUM 10
#define key(A) (A)
#define more(A, B) (key(A) > key(B))
#define exch(A, B) { Item t = A; A = B; B = t; }


Item select(Item a[], int left, int right, int k);
int partition(Item a[], int left, int right);

#include <stdio.h>

int main(void)
{
    Item a[NUM] = {2,2,3,1,8,3,6,4,3,7};
    int rec = 5; // 寻找的第 k 大的数。
    Item value;

    value = select(a, 0, NUM-1, rec-1);
    printf("%d\n", value);
    getchar();
    return 0;
}

Item select(Item a[], int left, int right, int k)
{
    int i;
    while (right > left)
    {
        i = partition(a, left, right);
        if (i >= k)
            right = i-1;
        if (i <= k)
            left = i+1;
    }

    return a[k];
}

int partition(Item a[], int left, int right)
{
    int i = left-1, j = right;
    Item v = a[right];

    while (1)
    {
        while (more(a[++i], v))
            continue;
        while (more(v, a[--j]))
        {
            if (j == left)
                break;
        }
        if (i >= j)
            break;
        exch(a[i], a[j]);
    }
    exch(a[i], a[right]);
    return i;
}

我就是真命天子,顺我者生,逆我者死!
2010-07-31 11:03
Devil_W
Rank: 10Rank: 10Rank: 10
等 级:青峰侠
威 望:9
帖 子:1160
专家分:1797
注 册:2009-9-14
收藏
得分:0 
程序代码:
#include<iostream>
#include<cstdlib>
#include<utility>
#include<cassert>
using std::pair;
template<class Type>
class List
{
public:
    struct Node{
    Type val;
    Node():pre(this),next(this){}
    Node(Type key):pre(this),next(this)
        {
        val=key;
        }
    Node(Node &node)
        {
        this->val=node.val;
        }
    Node &operator=(Node & node)
        {
        this->val=node.val;
        }
    ~Node()
        {
        
        }
    friend std::ostream & operator<<(std::ostream &os,Node &node)
        {
        os<<node.val<<" ";
        return os;
        }
    Node* pre;
    Node* next;
    };
    typedef Node* iter;
    List()
    {
        tail=new Node();
    }
    virtual ~List(){
    destroy();
    assert( tail->next==tail);
    delete tail;
    }
    std::size_t size();
    virtual void insert(Type key);
    virtual void erase(iter it);
    iter begin(){ return tail->next;}
    iter end(){ return tail;}
    void walk();
protected:
    void swap(Node  &n1,Node &n2)
    {
        Node tmp=n1;
        n1=n2;
        n2=tmp;
    }
    void destroy();
private:
    iter tail;
};

template<class Type>
void List<Type>::insert(Type key)
{
    if( NULL==tail )
    {
    tail=new Node(key);
    tail->pre=tail;
    tail->next=tail;
    }
    else
    {
    iter it=new Node(key);
    it->pre=tail->pre;
    it->pre->next=it;
    it->next=tail;
    it->next->pre=it;
    }
}
template<class Type>
void List<Type>::erase(iter it)
{
    it->pre->next=it->next;
    it->next->pre=it->pre;
    delete it;
}
template<class Type>
std::size_t List<Type>::size()
{
    if( tail==tail->next)
    return 0;
    else
    {
    std::size_t sz=0;
    for(iter it=begin();it!=end();it=it->next)
    {
        sz++;
    }
    return sz;
    }
}
template<class Type>
void List<Type>::walk()
{
    iter it=tail;
    if( NULL != tail)
    {
    for(it=tail->next;it!=tail;it=it->next)
    {
        std::cout<<*it<<" ";
    }
    std::cout<<std::endl;
    }
}
template<class Type>
void List<Type>::destroy()
{
    for(List<Type>::iter it=begin();it !=end();it=it->next)
    {
    erase(it);
    }
}
template<class Type>
class Rank:public List<Type>{
public:
    Rank():List<Type>(){}
    void qsort()
    {
        sort(1,List<Type>::size(),List<Type>::begin(),(List<Type>::end())->pre);
    }
    typename List<Type>::Node * _rank_k(int k);
    ~Rank(){}
protected:
    pair<typename List<Type>::Node*,int> 
    partition(int p,int r,typename List<Type>::Node * pt,typename List<Type>::Node* rt)
        {
             Type x=rt->val;
        int i=p-1,j;
        typename List<Type>::Node* it;
        typename List<Type>::Node* jt;
        it=pt->pre;
        jt=pt;
        for(j=p;j<r;j++)
        {
        if(jt->val<=x)
        {
            i=i+1;
            it=it->next;
            swap(*it,*jt);
        }
        jt=jt->next;
        }
        swap(*(it->next),*rt);
        return std::make_pair(it->next,i+1);
    }
    void sort(int p,int r,typename List<Type>::Node* pt,typename List<Type>::Node* rt)
    {
        if( p< r )
        {
        pair<typename List<Type>::Node*,int> qt;
        qt=partition(p,r,pt,rt);
        sort(p,qt.second-1,pt,qt.first->pre);
        sort(qt.second+1,r,qt.first->next,rt);
        }
    }
    typename List<Type>::Node* select(int p,int r,int i,typename List<Type>::Node* pt,typename List<Type>::Node* rt);
}; 
template<class Type>
typename List<Type>::Node * Rank<Type>::_rank_k(int k)
{
    assert(k+1<=List<Type>::size() &&k+1>0);
    return select(1,List<Type>::size(),k+1,List<Type>::begin(),List<Type>::end());
}
template<class Type>
typename List<Type>::Node* 
Rank<Type>::select(int p,int r,int i,typename List<Type>::Node*pt,typename List<Type>::Node * rt)
{
    if( p == r )
    {
    return pt;
    }
    pair<typename List<Type>::Node *,int>qt;
    qt=partition(p,r,pt,rt);
    int k=(qt.second)-p+1;
    if( i == k )
    return qt.first;
    else if( i< k)
    return select(p,qt.second-1,i,pt,qt.first->pre);
    else
    return select(qt.second+1,r,i-k,qt.first->next,rt);
}
int main()
{
    srand(time(NULL));
    Rank<int> rank;
    for(int i=0;i<10;i++)
    {
    int key=rand()%50;
    rank.insert(key);
    }
    rank.walk();
    //std::cout<<rank.size()<<std::endl;
    std::cout<<*(rank._rank_k(5))<<std::endl;
    //rank.qsort();
    //rank.walk();
    return 0;
}


BlueGuy的算法是对了。
Partition的行为有很大需要改进的。
看看我之要顺序扫描,而不是先从后向前,再从前向后迭代的算法。
2010-07-31 12:28
快速回复:有多少人写程序必须经常用到递归的?
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.020537 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved