在不使用堆栈的情况下将链接列表检查为回文

时间:2014-12-26 10:12:34

标签: c++ algorithm

以下是检查链接列表 Palindrome是否的代码。我编写的代码非常简单冗长,因为它有很多 REDUNDANT 代码。我可以降低 Big O 复杂性保持相同的逻辑。

仅仅因为我必须跳过 中间节点以防奇数链接列表我最终使代码变得多余。我在奇数链表的代码中添加的额外部分是

 `head_new = temp->next; 

// NEEDED TO SHIFT ONE POSITION SINCE MIDDLE NODE DOES NOT NEED ANY CHECKING!!!` 

有什么方法可以让我的代码整齐,而且冗余代码更少。

void linklist::palindrome()
{
    node *prev = NULL;
    node *curr = new node;
    node *next = new node;
    node *head_new = new node;
    node *temp;
    temp = head;
    curr = head;
    int t = 0,flag=0,flag_new=0;
    while (curr != NULL) // calculating the length of llinked list
    {
        curr = curr->next;
        t++;
    }
    curr = head; // Making sure curr is pointing to the head
    if (t % 2 == 0) // checking whether the linked list is even or odd
    {
        flag = 1;
    }
    if (flag == 1) // if linked list is even
    {
        for (int i = 0; i < t / 2 ; i++) // traversing till the half
        {
            temp = temp->next;
        }
        head_new = temp; // making sure head_new points to the head of other half
        for (int i = 0; i < t / 2; i++) // logic to do the reverse first half of the linked list
        {
            next = curr->next;
            curr->next = prev;
            prev = curr;
            curr = next;
        }
        head->next = NULL;
        head = prev;
        while (head && head_new) // comparing the reversed first half with the second half
        {
            if (head->data != head_new->data)
            {
                cout << "Not palindrome";
                flag_new = 1;
                break;  
            }
            else
            {
                head = head->next;
                head_new = head_new->next;
            }           
        }
        if (flag_new==0)
        cout << "Palindrome";
    }   
    else
    {
        for (int i = 0; i < t / 2; i++)// logic to do the traverse first half of the linked list
        {
            temp = temp->next;
        }
        head_new = temp->next; // ***NEEDED TO SHIFT ONE POSITION SINCE MIDDLE NODE DOES NOT NEED ANY CHECKING!!!***
        for (int i = 0; i < t / 2; i++) // logic to do the reverse first half of the linked list
        {
            next = curr->next;
            curr->next = prev;
            prev = curr;
            curr = next;
        }
        head->next = NULL;
        head = prev;
        while (head && head_new)// comparing the reversed first half with the second half
        {
            if (head->data != head_new->data)
            {
                cout << "Not palindrome";
                flag_new = 1;
                break;
            }
            else
            {
                head = head->next;
                head_new = head_new->next;
            }
        }
        if (flag_new == 0)
            cout << "Palindrome";

    }
}

1 个答案:

答案 0 :(得分:2)

以下可能会有所帮助:

int get_size(const node* n)
{
    int res = 0;
    while (n != 0) {
        ++res;
        n = n->next;
    }
    return res;
}

node* advance(node* n, int count)
{
    for (int i = 0; i != count; ++i) {
        n = n->next;
    }
    return n;
}

node* reverse(node* n, int count)
{
    node* prev = nullptr;
    for (int i = 0; i != count; ++i) {
        node* next = n->next;
        n->next = prev;
        prev = n;
        n = next;
    }
    return prev ? prev : n;
}

bool are_equal(const node* head1 , const node* head2)
{
    const node* n1 = head1;
    const node* n2 = head2;
    for (;
        n1 != nullptr && n2 != nullptr;
        n1 = n1->next, n2 = n2->next) {
        if (n1->data != n2->data)
        {
            return false;
        }
    }
    return n1 == n2;
}


void linklist::palindrome()
{
    const int t = get_size(head);
    node *mid = advance(head, (t + 1) / 2);
    node* head2 = advance(mid, 1);
    node* head1 = reverse(head, t / 2);

    if (are_equal(head1, head2)) {
        std::cout << "Palindrome";
    } else {
        std::cout << "Not palindrome";
    }
    // Restore list
    reverse(head1, t / 2);
    mid->next = head2;
}