數據結構之單向環形鏈表

介紹

和單向鏈表的惟一區別就是,在鏈表最後的節點指向了鏈表的頭節點.

微信圖片_20191219150059.png

案例:

單向環形鏈表經典的案例就是約瑟夫環的問題,引伸出來相似猴子選大王,丟手帕等都是約瑟夫的實際場景.
假設有編號爲1,2,3...n的人圍成一圈,約定編號爲k(1 <= k <= n)的人開始報數,數到m的那我的出列,他的下一位又從1開始報數,數到m的那我的在出列,以此類推,直到全部人出列完畢,由此產生出一個出隊的編號序列.
  • 構建節點類,每一個節點表明一我的,節點包含編號和next域
class Node
{
    public $no;
    public $next;

    public function __construct($no)
    {
        $this->no = $no;
    }
}
  • 建立一單向環形鏈表的類
class CircleLinkedList
{
    public $first;
}
  • 生成一個長度爲total的單向環形鏈表,這裏須要兩個變量$first和$cur,$first指向鏈表的頭節點,$cur指向當前鏈表的最後一個節點.
public function addNode($total)
{
    $cur = null;
    //循環插入$total個節點
    for ($i = 1; $i <= $total; $i++) {
        $boy = new Node($i);
        if ($i == 1) {
        //若是是第一個節點,則將$first指向它.
            $this->first = $boy;
            $cur = $boy;
        } else {
        //新的人的next域指向第一人,造成一個環狀.
            $boy->next = $this->first;
            //將$cur後移之下新的人
            $cur->next = $boy;
            $cur = $boy;
        }
    }
}
  • 出圈思路:
  1. 新建兩個變量$temp和$helper,現將$temp指向$first,$helper指向鏈表的最後一我的.
  2. 將$temp和$helper都移動k-1位,找到開始報數的那我的.
  3. 當$temp開始報數時,$temp和$helper同時移動$num位.
  4. 最後將$helper的next域指向$temp的next,$temp向後移動一位,即完成出列.
  5. 循環第二步,直到$temp == $helper說明鏈表只剩下一我的,出列完畢.
public function leaveCircle($k, $num)
{
    //現將$temp指向$first
    $temp = $this->first;
    //而後經過遍歷將$temp指向鏈表的最後一我的.
    while (true) {
        if ($temp->next == $this->first) {
            break;
        }
        $temp = $temp->next;
    }
    //$temp和$helper移動k-1位找到開始報數的那我的
    for ($i = 0; $i < $k - 1; $i++) {
        $this->first = $this->first->next;
        $temp = $temp->next;
    }
    //循環遍歷出列
    while (true) {
        //若是$first == $temp說明鏈表只剩下一個節點,退出循環
        if ($this->first == $temp) {
            break;
        }
        //開始報數,$temp和$helper開始移動
        for ($i = 0; $i < $num - 1; $i++) {
            $this->first = $this->first->next;
            $temp = $temp->next;
        }
        //$this->frist指向報數結束後的那我的
        echo "\n" . "編號爲" . $this->first->no . "的人出圈";
        //將當前指針$frist移動到下一個,而後讓$temp的next指向$first,完成出圈
        $this->first = $this->first->next;
        $temp->next = $this->first;

    }
    echo "\n" . "最後一我的的編號爲:" . $this->first->no;
}
相關文章
相關標籤/搜索