Check for cyclic list (count the length of circle)

The "hare and tortoise" algorithm

(define gk-list?
    (lambda (ls)
         (let race ([h ls] [t ls])
               (if (pair? h)
                   (let ([h (cdr h)])
                        (if (pair? h)
                            (and (not (eq? h t)) (race (cdr h) (cdr t)))
                            (null? h)))
                   (null? h)))))

The function will check if a list is proper list.

If (eq? h t) is true, then there is a cycle in the list, from there, let h keep running and t stay until h equal t again, we can know the length of the cycle.

(define test-list?
  (lambda (ls)
    (let race ((h ls) (t ls))
      (if (pair? h)
          (let ((h (cdr h)))
            (if (pair? h)
                (if (eq? h t)
                    (test-length h)
                    (race (cdr h) (cdr t)))
                (null? h)))
          (null? h)))))

(define test-length 
  (lambda (ls)
    (let count ([from (cdr ls)] [cnt 1])
      (if (eq? from ls)
          cnt
          (count (cdr from) (+ cnt 1))))))


Here is the C++ version:
#include <iostream>
using std::cout;
using std::endl;

struct item {
    int value;
    item *next;
    item(int value): value(value), next(NULL) {}
};
struct result {
    bool isList;
    int cycleLength;
    result(bool isList, int cycleLength):isList(isList), cycleLength(cycleLength) {}
    void dump() {
        cout << "{" << isList << "," << cycleLength << "}" << endl;
    }
};

int getCycleLength(item *h) 
{
    item *from, *to;
    int count;

    to = h;
    from = h->next;
    for (count = 1; from != to; from = from->next, ++count);
    return count;
}
result race(item *h, item* t) 
{
    for (;h != NULL; h = h->next, t = t->next) {
        h = h->next;
        if (h == NULL) return result(true, -1);
        else if (h == t) return result(false, getCycleLength(h));
    }
    return result(true, -1);
}

result isList(item *list) 
{
    return race(list, list);
}

int main(int argc, char **argv) 
{
    item *a = new item(0),
         *b = new item(1),
         *c = new item(2);
    a->next = b;
    b->next = c;
    c->next = a;

    isList(a).dump();
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值