| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1638 人关注过本帖, 3 人收藏
标题:基于链表结构的 求第 k大的数,时间效率O(n) (广陵,我把代码贴了)
只看楼主 加入收藏
Devil_W
Rank: 10Rank: 10Rank: 10
等 级:青峰侠
威 望:9
帖 子:1160
专家分:1797
注 册:2009-9-14
结帖率:100%
收藏(3)
 问题点数:0 回复次数:9 
基于链表结构的 求第 k大的数,时间效率O(n) (广陵,我把代码贴了)
之前出的题目,基于链表结构,在O(n)的时间里面求第k大的数。

到现在为止都没看到让我满意的代码。

现在应广陵之前之邀把代码贴出来。

不足的地方,请指正。

程序代码:
#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;
}


编译器g++ 4.0以上。
搜索更多相关主题的帖子: 时间 代码 结构 效率 链表 
2010-03-27 16:00
hahayezhe
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖南张家界
等 级:贵宾
威 望:24
帖 子:1386
专家分:6999
注 册:2010-3-8
收藏
得分:0 
居然用模板类写的 应该贴C++那里了
2010-03-27 16:03
Devil_W
Rank: 10Rank: 10Rank: 10
等 级:青峰侠
威 望:9
帖 子:1160
专家分:1797
注 册:2009-9-14
收藏
得分:0 
这里代码能写到我这级别的,还有谁?
2010-03-27 19:30
longlong89
Rank: 11Rank: 11Rank: 11Rank: 11
来 自:广州
等 级:小飞侠
威 望:6
帖 子:1043
专家分:2754
注 册:2009-8-18
收藏
得分:0 
以下是引用Devil_W在2010-3-27 19:30:27的发言:

这里代码能写到我这级别的,还有谁?

冲LZ的这句话,看看。

想象力征服世界
2010-03-27 21:27
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
收藏
得分:0 
是挺牛的

我就是真命天子,顺我者生,逆我者死!
2010-03-27 21:35
asdjc
Rank: 6Rank: 6
来 自:武汉
等 级:侠之大者
威 望:7
帖 子:98
专家分:487
注 册:2010-1-22
收藏
得分:0 
很好,很强大。不过好像是用书上的代码,太复杂。而且这段代码只是平均时间复杂度为O(n),可是又加大了空间复杂度。
根据我自己理解的写个简单易懂的。
int kth_a[n](int &a,int k)
{
    int *t,*key;
    int l=0,r=n-1,i,j;
    while (l<r)
   {
        for (key=a[((i=l)+(j=r+1))/2];i<j;)
        {
            for (j--;key<a[j];);//从右到左找到比key大的数,a[j]
            for (i++;a[i]<key;);//从左到右找到比key小的数,a[i]
            if (i<j) t=a[i],a[i]=a[j],a[j]=t;
        }//此时a[]被分为左边a[0..j-1]比a[j]小,a[j+1..n]比a[j]大
        if (k>j) l=j+1;//k为j右方的数
        else r=j;
    }
    return a[k];
}
看起来并非在O(n)内完成,但平均时间是o(n).
2010-03-28 10:20
阿邋
Rank: 2
等 级:论坛游民
帖 子:84
专家分:41
注 册:2009-3-6
收藏
得分:0 
学习了,楼主你牛!

我并不具有我想要的一切,只是我所有的都是我想要的!
2010-03-28 10:29
Devil_W
Rank: 10Rank: 10Rank: 10
等 级:青峰侠
威 望:9
帖 子:1160
专家分:1797
注 册:2009-9-14
收藏
得分:0 
要求是在链表的基础上。

用数组,用线段树,效率可以更高。

基于链表的,我这个是极致了。
2010-03-28 10:29
asdjc
Rank: 6Rank: 6
来 自:武汉
等 级:侠之大者
威 望:7
帖 子:98
专家分:487
注 册:2010-1-22
收藏
得分:0 
你可不可以把大致思想说说,代码太长,不想看。你视乎是学过算法的,同道中人。学一学,
2010-03-28 14:36
cnfarer
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:179
帖 子:3330
专家分:21157
注 册:2010-1-19
收藏
得分:0 
回复 6楼 asdjc
同感!不过他原来贴是有两个条件的(时间\空间),现在好像只达到一个条件!

★★★★★为人民服务★★★★★
2010-03-28 16:08
快速回复:基于链表结构的 求第 k大的数,时间效率O(n) (广陵,我把代码贴了) ...
数据加载中...
 
   



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

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