STL算法我实现之rotate

简介: STL算法我实现之rotate

STL在rotate上的优化是极尽其所能的。分别对前向访问,双向访问,随机访问的数据结构实现了三个版本的rotate。下面是自己按照对三种算法的理解,自己进行的实现。实现中我尽力避免使用C++的特性,从而以后可以在纯C的代码中使用。

下面是我使用到的数据结构,单向链表与双向链表,用于实现算法和验证算法的正确性:

//单链表节点
typedef struct Node* Link;
struct Node{
    int value;
    Link next;
    Link forward(Link& i)
    {
        i=i->next;
        return i;
    }
    void swap(Link& i)
    {
        int temp=i->value;
        i->value=this->value;
        this->value=temp;
    }
};
typedef struct BiNode* BiLink;
struct BiNode{
    int value;
    BiLink next;
    BiLink prev;
    BiLink forward(BiLink& i)
    {
        i=i->next;
        return i;
    }
    BiLink backward(BiLink& i)
    {
        i=i->prev;
        return i;
    }
    void swap(BiLink& i)
    {
        int temp=i->value;
        i->value=this->value;
        this->value=temp;
    }
};

版本一:forward iterator,即类单向链表上的rotate

//forward iterator,即类单向链表
void forwardRotate(Link head,Link middle)
{
    Link i=middle;
    while(true)
    {
        head->swap(i);
        head->forward(head);
        i->forward(i);
        if(head==middle)
        {
            if(i==NULL) return ;            //如果前后两指针同时到达末尾,则结束
            middle=i;                       //如果前者先到达末尾,则将i作为middle,继续rotate
        }
        else if(i==NULL)
            i=middle;                       //如果后者先到达末尾,则将middle作为i,继续rotate
    }
}

另附上注释的图像版以帮助理解:

版本二:bidirection iterator,即类双向链表上的rotate

这个版本的算法很容易理解,即是分段进行反转,之后对左右数据进行反转,代码如下:

void reverse(BiLink first,BiLink last)
{
    while(first!=last &&first!=last->backward(last))
    {
        last->swap(first);
        first->forward(first);
    }
}
void bidirectionRotate(BiLink first,BiLink middle,BiLink last)
{
    reverse(first,middle);
    reverse(middle,last);
    reverse(first,last);
}

版本三:random access iterator,即类数组上的rotate

该版本的效率无疑是最高的,当然算法因为涉及到有关群论的知识所以有点难以理解。其理论支持详见:数组循环移位问题

自己实现版本的代码如下:

//求最大公约数
int gcd(int m,int n)
{
    int t;
    while(n!=0)
    {
        t=m%n;
        m=n;
        n=t;
    }
    return m;
}
//循环移位
void rotate_cycle(int array[],int len,int initial,int shift)
{
    int value=array[initial];
    int first=initial;
    int next=initial+shift;
    while(next!=initial)
    {
        array[first]=array[next];
        first=next;
        next=(next+shift)%len;
    }
    array[first]=value;
}
void randomRotate(int array[],int middle,int len)
{
    int n=gcd(len,middle);
    while(n--)
        rotate_cycle(array,len,n,middle);
}

最后附上我自己的测试代码:

int main()
{
    int len=20;
    srand(time(0));
    //单向访问链表的rotate
    Link head=new Node;
    head->value=25;
    cout<<head->value<<"\t";
    Link p=head;
    Link middle;
    for(int i=0;i<len;i++)
    {
        Link next=new Node;
        p->next=next;
        next->value=rand()%200;
        cout<<next->value<<"\t";
        if(i==len/4*3)
            middle=p;
        p=p->next;
    }
    cout<<endl;
    p->next=NULL;
    forwardRotate(head,middle); 
    p=head;
    while(p!=NULL)
    {
        cout<<p->value<<"\t";
        p=p->next;
    }
    cout<<endl;
    //双向链表的rotate
    BiLink bihead=new BiNode;
    bihead->value=25;
    cout<<bihead->value<<"\t";
    BiLink bip=bihead;
    BiLink bimiddle;
    for(int i=0;i<len;i++)
    {
        BiLink binext=new BiNode;
        bip->next=binext;
        binext->prev=bip;
        binext->value=rand()%200;
        cout<<binext->value<<"\t";
        if(i==len/4)
            bimiddle=bip;
        bip=bip->next;
    }
    cout<<endl;
    BiNode end;
    bip->next=&end;
    end.prev=bip;
    bidirectionRotate(bihead,bimiddle,&end);  
    bip=bihead;
    while(bip!=&end)
    {
        cout<<bip->value<<"\t";
        bip=bip->next;
    }
    cout<<endl;
    int array[len];
    for(int i=0;i<len;i++)
    {
        array[i]=rand()%200;
        cout<<array[i]<<"\t";
    } 
    cout<<endl;
    randomRotate(array,len/3,len);
    for(int i=0;i<len;i++)
        cout<<array[i]<<"\t";
    cout<<endl;
    return 0;
}

OK,大致如此了。三个版本的rotate,极至的优化手段,这也许就是STL的魅力所在吧。

本文作者 : cyningsun

本文地址https://www.cyningsun.com/04-25-2011/stl-rotate.html

版权声明 :本博客所有文章除特别声明外,均采用 CC BY-NC-ND 3.0 CN 许可协议。转载请注明出处!

# STL

  1. STL算法我实现之随机洗牌
  2. STL算法我实现之排列
  3. SGI-STL源码剖析之IntroSort
  4. SGI-STL源码剖析之list::sort()
  5. SGI-STL源码剖析之Heap
目录
相关文章
|
2月前
|
算法 数据处理 C++
c++ STL划分算法;partition()、partition_copy()、stable_partition()、partition_point()详解
这些算法是C++ STL中处理和组织数据的强大工具,能够高效地实现复杂的数据处理逻辑。理解它们的差异和应用场景,将有助于编写更加高效和清晰的C++代码。
37 0
|
6月前
|
算法 前端开发 Linux
【常用技巧】C++ STL容器操作:6种常用场景算法
STL在Linux C++中使用的非常普遍,掌握并合适的使用各种容器至关重要!
95 10
|
5月前
|
算法 C++
STL算法大全
以上只是一部分STL算法的简单概述,每一个算法都有其特定的使用场景和规则,具体使用时需要参考相关文档或者教程进行深入理解和学习。
35 0
|
6月前
|
算法 搜索推荐 C++
C++之STL常用算法(遍历、查找、排序、拷贝、替换、算数生成、集合)
C++之STL常用算法(遍历、查找、排序、拷贝、替换、算数生成、集合)
|
7月前
|
算法 C++ 容器
黑马c++ STL常用算法 笔记(5) 常用算术生成算法
黑马c++ STL常用算法 笔记(5) 常用算术生成算法
|
7月前
|
算法 C++ 容器
黑马c++ STL常用算法 笔记(4) 常用拷贝和替换算法
黑马c++ STL常用算法 笔记(4) 常用拷贝和替换算法
|
7月前
|
存储 算法 搜索推荐
黑马c++ STL常用算法 笔记(3) 排序算法
黑马c++ STL常用算法 笔记(3) 排序算法
|
7月前
|
算法 C++
黑马c++ STL常用算法 笔记(2) 查找算法
黑马c++ STL常用算法 笔记(2) 查找算法
|
6月前
|
算法 计算机视觉
图像处理之线性插值旋转算法(biline-interpolation rotate algorithm)
图像处理之线性插值旋转算法(biline-interpolation rotate algorithm)
65 0
|
7月前
|
算法 C++
c++算法学习笔记 (21) STL
c++算法学习笔记 (21) STL