在c++链表中,使用递归还是迭代来分隔偶数和奇数长度的字符串更好?

Is it better to use recursion or iteration to separate the even and odd length strings in a C++ linked list?

本文关键字:更好 字符串 分隔 链表 c++ 迭代 归还 递归      更新时间:2023-10-16

早上好。在c++链表中使用递归或迭代来分离偶数和奇数长度的字符串更好吗?

更好意味着1)健壮性2)跨平台Windows/Linux/Unix可移植性3)最坏情况下运行时性能

cSinglyLinkedList* SeparateOddandEvenlLengthStrings(cSinglyLinkedList* list){
    cSinglyLinkedList* Retval(NULL);
    char* Temp(NULL);
    if (list == NULL || list->Head == NULL){
        return NULL;
    }
    if (list && list->Current && list->Current->Next == NULL){
        return list;
    }
    if (list->Iterate()){
        Temp = list->Current->String;
        Retval = SeparateOddAndEvenLengthStrings(list);
        if ((strlen(Temp) % 2) == 0){
            Retval->Remove(Temp);       
            Retval->Add(Temp);
        }
        return Retval;
    }
    return NULL;
}
class cSinglyLinkedList {
private:
    struct SinglyLinkedInfo{
        SinglyLinkedInfo* Next;
        char* String;
        SinglyLinkedInfo(void){
            Next =  0;
            String= 0;
        }
    } Item;
    SinglyLinkedInfo *Head, *Current; 
    int Count;
    void ClearStrings(void);
public:
    cSinglyLinkedList(void);
    ~cSinglyLinkedList(void);
    bool Add(const char *string1);
    void Remove(const char *string1);
    bool RestartIterator(void);
    bool Iterate(void);
    int GetCount(void);
    SinglyLinkedInfo* GetHead(void);
    SinglyLinkedInfo* GetCurrent(void);
    void Trace(const char *title_);
};
inline bool cSinglyLinkedList::RestartIterator(void) {
    Current=Head;
    return (Current!=0);
}
inline bool cSinglyLinkedList::Iterate(void) {
    if (Current==0){
        Current=Head;
    } else if (Current){ 
        Current = Current->Next;
    }
    return (Current!=0);
}
inline SinglyLinkedInfo *cSinglyLinkedList::GetHead(void) {
    return Head;
}
inline SinglyLinkedInfo *cSinglyLinkedList::GetCurrent(void) {
    return Current;
}
cSinglyLinkedList::cSinglyLinkedList(void) {
    Head=Current=0;
    Count=0;
}
cSinglyLinkedList::~cSinglyLinkedList(void) {
    ClearStrings();
}
void cSinglyLinkedList::ClearStrings(void) {
    SinglyLinkedInfo* nextCurrent;
    Current=Head;
    while (Current!=0) {
        nextCurrent = Current->Next;
        delete[] Current;
        Current=nextCurrent;
    }
    Head=Current=0;
    Count=0;
}
void cSinglyLinkedList::Remove(const char* string1_) {
    SinglyLinkedInfo* Prev(NULL);
    RestartIterator();
    Current = Head;
    while (Current!=0) {
        if (strcmp(Current->String,string1_)==0){       
            if (Prev){
                Prev->Next = Current->Next;
            } else{
                Head = Current->Next;
            }
            delete [] Current;
            break;
        }
        Prev=Current;
        Current=Current->Next;
    }
    RestartIterator();
    Count -= 1;
}
bool cSinglyLinkedList::Add(const char *string1_){ 
    SinglyLinkedInfo* newElement = (SinglyLinkedInfo*)new char[sizeof(SinglyLinkedInfo)];
    memset(newElement, 'x0', sizeof(SinglyLinkedInfo)); 
    newElement->String = new char[sizeof(char*)];
    memcpy(newElement->String, &string1_, sizeof(char*));
    newElement->String = (char*)string1_; 
    newElement->SinglyLinked = new cPCRE();
    newElement->SinglyLinked->SetOptions(PCRE_CASELESS);
    if (newElement->SinglyLinked->Compile(string1_) == 0){
        return false;
    }
    if (Head==0) {
        Head = newElement;
    } else {
        SinglyLinkedInfo* Temp(NULL);
        Temp = Head;
        while (Temp != 0 && Temp->Next != 0){
            Temp = Temp->Next;
        }
        Temp->Next = newElement;
    }
    Count++;
    return true;
}
void cSinglyLinkedList::Trace(const char *title_) {
    int i=0;
    if (title_!=0)
        printf("%s:n",title_);
    if (RestartIterator()) {
        do {
            printf(" %d: %sn",i++,GetString());
        } while (Iterate());
    }
}

尽管由于尾部调用优化,它最终可能无关紧要,但至少就c++而言,迭代方法处理链表更为惯用。与递归方法不同,迭代方法不会导致堆栈溢出,即使编译器不应用尾部调用优化。

不"有界"的递归[1]绝对是一件坏事。如果有人给你的函数输入莎士比亚全集(我指的是所有的书,而不是"莎士比亚全集",它大约有32个字符长),会发生什么?

无界递归的问题是,它会以一种你无法恢复的方式爆发,因为一旦堆栈被完全用完,任何人都无能为力,只能终止进程。你不能调用一个函数说"对不起,我的堆栈用完了",因为这会占用堆栈空间!

[1]或者你可以合理地说,这将是好的与给定数量的递归调用,例如一个合理平衡的二叉树可以在32个递归搜索40亿个条目的水平,所以如果您的数据库是不会超过几百万条目(还有防范病理情况下的所有节点都在一个链表的左边或者右边的树),那么你能说没关系。

根据我的经验,我可以说对于任何算法,迭代版本总是比递归版本快。递归版本也可能导致溢出,因为递归的长度是有限的。但是,递归实现的一个优点是,它们非常简单。

相关文章: