2013-12-26 2 views
-1

Поиск цикла в одиночном списке и поиск узла, с которого начинается цикл. Я видел использование двух указателей (как правило, медленных и быстрых), чтобы найти цикл, но я написал этот код и, похоже, работает нормально. Мой вопрос в том, есть ли что-то, чего не хватает моему коду, при поиске цикла в одиночном списке.Поиск цикла в одиночном списке

Node* find_cycle_node(Node *head){ 
Node *p=head; 
    Node *q; 
    while(p->next!=null) 
    { 
       q=p->next; 
     while(q->next!=null) 
      { 
        if(p==q) return q; //Node repeated i.e cycle 
        else (q=q->next;) 
      } 
       p=p->next; 
     } 
    return null; // no cycle detected 
} 
+0

с 'return;', вы получите ошибку компиляции. 'return NULL', если цикл не обнаружен – David

+1

Этот сайт не для отзывов о кодах. Если у вас нет конкретной проблемы с кодом, который вы не понимаете, тогда вам следует попросить общую обратную связь в другом месте. –

+0

Ну, я думаю, одна вещь, которую вы можете рассмотреть, - это не только правильность, но и время исполнения. Ваш алгоритм выглядит так, как будто он работает в O (n^2), тогда как двунаправленный (черепаха и зайчик) работает как-то вроде O (n). –

ответ

0

есть что-то мой код отсутствует на

return; // no cycle detected 

Эта линия выглядит очень плохо, он должен быть изменен на s.th. как

return NULL; // no cycle detected 
+0

Спасибо, отредактирован! Я этого не заметил, так как это было важно! но, хорошая находка. Еще раз спасибо. – user2773985

5

Ваш внутренний цикл не прекращается, если есть цикл, который является пара узлов ручки вниз, например, это будет бесконечный цикл что-то вроде этого:

1 -> 2 -> 3 -> 4 -> 5 
     ^  | 
      |   | 
      +---------+ 
+0

Прошу прощения, но я не понял этого. Когда указатель p входит в узел 3, указатель q будет установлен на узел 4, а затем на узел 5 и, наконец, на узел 3. Теперь мое условие будет истинным (p == q), теперь оно вернет узел q (т. Е. 3) и программа завершится. – user2773985

+0

@ user2773985: в первой внешней итерации 'p' находится в узле 1.' q' инициализируется узлом 2, перемещается в узел 3 и продолжает бесконечно проходить последовательность 4, 5, 3. Он никогда не достигнет узла, где следующий указатель будет нулевым, и он никогда не станет равным 'p'. –

+0

О, вот и все! Я не смог найти эту ошибку. Великий Поймать. – user2773985

0

мне ваш условие внутреннего цикла кажется неоднозначным. Вы анализируете if (p == q), где q - p-> next. это означает, что ранее рассмотренный узел p не составлял haD A CYCLE. Таким образом, моя внутренняя петля никогда не прекратится.

вы должны учитывать следующее: -

#include <iostream> 
using namespace std; 
class Node{ 
    public: 
     int data; 
     Node * next; 
     Node(int x){ 
      data = x; 
      next = NULL; 
     } 
     Node(int x, Node * y){ 
      data = x; 
      next = y; 
     } 
}; 
class linkedList{ 
    Node *head; 
    public: 
     linkedList(){ 
      head = NULL; 
     } 
     void addNode(int value){ 
      Node *p; 
      if(head == NULL) 
       head = new Node (value, NULL); 
      else{ 
       p = head; 
       while(p->next !=NULL) 
        p=p->next; 
        p->next = new Node (value, NULL); 
      } 
     } 
     void print(){ 
      Node * p; 
      p = head; 
      while(p != NULL){ 
       cout << p->data; 
       p = p->next; 
      } 
     } 
     int findCycle(){ 
      Node *p, *start, *q; 
      p = head; 
      while(p != NULL){ 
       q = p->next; 
       while (q != NULL){ 
        if(p->data == q->data) 
         return q->data; 
        else 
         q = q->next; 
       } 
       p = p->next; 
      } 
      return 0; 
     } 
}; 
int main(){ 
    linkedList l1; 
    l1.addNode(1); 
    l1.addNode(2); 
    l1.addNode(3); 
    l1.addNode(4); 
    l1.addNode(5); 
    l1.addNode(3); 
    int node = l1.findCycle(); 
    cout<<node; 
    return 0; 
} 

Что вы говорите людям об этом коде.

+0

Ваша версия также может иметь бесконечный цикл. – Jarod42

+0

@ Jarod42 Я обновил код. В настоящее время это не происходит в бесконечном цикле. , Но мой вопрос здесь в том, что тот, кто задал вопрос, ссылается на одни и те же данные в другом месте как на петлю - «Вопрос от взлома кодингового интервью». Мой код отвечает на одни и те же данные. и для того, чтобы это был цикл, относящийся к тому же узлу, нам просто нужно изменить условие if на «if (p == q)», это проверяет местоположение памяти. если ссылка на память одинакова, тогда будет цикл – yashgarg1232

+0

@ yashgard1232: OP хочет обнаружить цикл для плохо сформированного списка. Он не хочет находить дублированные ценности. Поэтому вы неправильно поняли этот вопрос. – Jarod42

1

Как насчет этого?

struct Node_ 
{ 
    int ix ; 
    struct Node_* next ; 
} ; 
typedef struct Node_ NODE ; 
NODE *head = NULL ; 

int main() 
{ 
    NODE* n1 ; 
    n1 = (NODE*) malloc(sizeof(NODE)) ; 
    n1->ix = 0 ; 
    n1->next = NULL ; 
    head = n1 ; 
    NODE* n2 ; 
    n2 = (NODE*) malloc(sizeof(NODE)) ; 
    n2->ix = 1 ; 
    n2->next = NULL ; 
    n1->next = n2 ; 
    NODE* n3 ; 
    n3 = (NODE*) malloc(sizeof(NODE)) ; 
    n3->ix = 2 ; 
    n3->next = NULL ; 
    n2->next = n3 ; 
    NODE* n4 ; 
    n4 = (NODE*) malloc(sizeof(NODE)) ; 
    n4->ix = 3 ; 
    n4->next = n2 ; 
    n3->next = n4 ; 

    unordered_map<NODE*,int> hashx ; 
    int idx ; 
    NODE* p = head ; 
    while(p != NULL) 
    { 
     hashx[p] += 1 ; 
     if(hashx[p] >= 2) 
     { 
      printf("node p (%d) recycle !!\n",p->ix); 
      break ; 
     } 
     p = p->next ; 
    } 
    printf("done \n") ; 
} //main 
0
void LinkListOps::createCycledListAndFindACycleNode() 

{ // создать список с циклом в его

ZNODE* head = new ZNODE(0); 
ZNODE* current = head; 
ZNODE* cycle = 0; 

for (int i = 1; i < 8; i++) 
{ 
    current->_next = new ZNODE(i); 
    current = current->_next; 

    if (i == 6) 
     cycle = current; 

    if (i == 7) 
     current->_next = cycle; 
} 

// verify that there is a cycle 
ZNODE* slow = head; 
ZNODE* fast = head; 
ZNODE* cycleNode = 0; 

while (slow && fast && fast->_next) 
{ 
    slow = slow->_next; 
    fast = fast->_next->_next; 

    if (slow == fast) 
    { 
     cycleNode = slow; 
     break; 
    } 

} 

if (cycleNode == 0) 
{ 
    printf("No cycle\n"); 
    return; 
} 

// finally find a cycle node which will be p2 
ZNODE* p1 = head; 
ZNODE* p2 = cycleNode; 

while (1) 
{ 
    for (p2 = cycleNode; p2->_next != cycleNode; p2 = p2->_next) 
    { 
     if (p2 == p1) 
      break;   
    } 

    if (p2 == p1) 
     break; 

    p1 = p1->_next; 
} 

printf("%d\n", p2->_i); 

}

0

Вы можете быстро узнать, если есть цикл в связанном списке, выполнив следующие:

ptr = head; 
current = nullptr; 
if (!ptr) { 
    current = ptr->next; 
    while(current && current!=ptr) { 
    current = current->next; 
    if (current) { 
     current = current->next; 
    } 
    ptr = ptr->next; 
    } 
} 

В конце этого, если current не имеет значения NULL, тогда был найден цикл, и current будет где-то внутри него. Это работает путем повторения current в два раза быстрее в списке как ptr и всегда найдет цикл, если он существует, до того, как ptr зациклился один раз.

Смежные вопросы