php 单向链表反转 reverse (没有空的头结点)

* 参照php标准库设计接口

http://php.net/manual/en/class.spldoublylinkedlist.php

* 反转单向链表

reverse方法, 其他的方法为了方便测试

<?php
/**
 * Created by PhpStorm.
 * User: Mch
 * Date: 8/11/18
 * Time: 00:25
 */
class Node {
    public $value;
    public $next;
    public function __construct($data) {
        $this->value = $data;
        $this->next = null;
    }
}

class LinkedList implements Iterator, Countable {
    private $head;
    private $cur;

    public function __construct() {
        $this->head = $this->cur = null;
    }

    public function isEmpty() {
        return is_null($this->head);
    }

    public function count() {
        $p = $this->head;
        $count = 0;
        while ($p !== null) {
            $p = $p->next;
            $count++;
        }
        return $count;
    }
    public function current() {
        if ($this->isEmpty()) {
            return null;
        }
        return $this->cur->value;
    }
    public function next() {
        if (is_null($this->cur)) {
            return null;
        }
        $this->cur = $this->cur->next;
    }
    public function rewind() {
        $this->cur = $this->head;
    }

    public function valid() {
        return !is_null($this->cur);
    }
    public function key() {
        $p = $this->head;
        $key = 0;
        while ($p !== $this->cur) {
            $p = $p->next;
            $key++;
        }
        return $key;
    }
    public function push($value) {
        if ($this->isEmpty()) {
            $this->head = new Node($value);
            $this->cur = $this->head;
        } else {
            $this->cur = $this->head;
            while ($this->cur->next !== null) {
                $this->cur = $this->cur->next;
            }
            $this->cur->next = new Node($value);
        }
        return $this;
    }

    public function forEach(callable $callback, mixed $userdata = null) {
        $this->rewind();
        while($this->valid()) {
            call_user_func($callback, $this->current(), $this->key(), $userdata);
            $this->next();
        }
    }

    public function reverse() {
        if ($this->isEmpty())
            return;
        if ($this->count() < 2)
            return;
        $prev = null;
        $cur = $this->head;
        while ($cur) {
            // save next
            $next = $cur->next;
            // move cur to head
            $this->head = $cur;
            $cur->next = $prev;
            // iterate
            $prev = $cur;
            $cur = $next;
        }
    }

}

  

* test

$list = new LinkedList();

for ($i = 65; $i < 91; $i++) {
    $list->push(chr($i));
}

$list->forEach(function($value, $index) {
    printf("[%d] => %s<br />", $index, $value);
});
echo ‘-------------------<br />‘;
$list->reverse();
$list->forEach(function($value, $index) {
    printf("[%d] => %s<br />", $index, $value);
});

  

* output:

[0] => A
[1] => B
[2] => C
[3] => D
[4] => E
[5] => F

....

-------------------
[0] => Z
[1] => Y
[2] => X
[3] => W
[4] => V
[5] => U
...

原文地址:https://www.cnblogs.com/mingzhanghui/p/9462187.html

时间: 2024-07-30 08:00:52

php 单向链表反转 reverse (没有空的头结点)的相关文章

单向链表反转算法——递归版和迭代版

最近在做笔试题时,遇到一道编程题:单向链表反转算法.一时紧张,没写出来就提前交卷了,然而交完卷就想出来了... 最初想出来的是递归版,遗憾的是没能做到尾递归,后来又琢磨出了迭代版.后来用实际编译运行测试了一遍,能正常运行. 递归版的灵感来源于<Haskell 趣学指南>中非常简洁的快速排序算法的实现,其思想是将单向链表分割头部和尾部.其中头部指是链表的第一个节点,尾部是指除去第一个节点后的子链表.通过递归的方法,将子链表继续分割成头部和尾部,直至尾部指剩下一个节点,无法继续分割,然后将头部和尾

小菜鸟的单向链表反转

关于单向链表的反转想必大家都很熟了,以前一直用递归的方法写的,还是挺好写的,但是后来又在网上瞄了一眼非递归方法的实现,当时以为那个代码是正确的,也没验证,后来就不了了之. 昨天下午开始写这个代码,最后老发现出问题,今天早上起来理了一遍,终于发现症结所在. 举个例子吧: 1->2->3->4->5->6       我反转后的结果应该是: 6->5->4->3->2->1 我的算法是这样的(语死早,大家不要笑,我就用过程图表达吧): 1->2

找出单向链表中的倒数第k个结点

import java.util.Scanner; public class List { private Node first; private int N; class Node{ int data; Node next; } //顺便复习一下链表 public int size() { return N; } public boolean isEmpty() { return first==null; } public Node FindPrev(int pos){ Node tmp=fi

单向链表反转,就地逆置与递归反转(无表头结点)

最近在看链表,今天刷到一道链表的反转题,链表反转可以说是基础操作,但是可提供的方案也有很多,简单通过了该题后又学习了一下递归反转,现在把三种方法都公开出来做一个总结. 1.就地逆置 2.单参数的递归逆置 3.双参数的递归逆置 一.就地逆置 方法:头插. 由于这里是不带表头结点的单向链表,所以头插会稍微复杂一点,不想往下看的小伙伴也可以直接选择定义一个临时表头结点从头结点开始遍历链表将每一个链表头插,最后将头结点指向表头结点的next指针域,最后free掉那个表头结点即可. 虽然不带表头结点头插会

Java实现单向链表反转

环境: Java: jdk1.8.0_91 public class LinkedListTest { public static void main(String[] args) { Node A = new Node("A"); Node B = new Node("B"); Node C = new Node("C"); Node D = new Node("D"); Node E = new Node("E&

链表(四)——带表头的单向链表

1.带表头的单向链表 (1)不带表头的单向链表在实现插入和删除时必须区分头结点和其他节点的处理. (2)使用带表头的单向链表的好处:不用考虑头结点的单独处理. 表头节点:数据域没有值,指针域指向单向链表中数据域含值的第一个结点. 2.代表头的单向链表的基本操作 #include <stdio.h> #include <malloc.h> #define NULL 0 typedef struct node { int data; struct node *next; }ElemSN

[算法]反转单向链表和双向链表

题目: 分别实现反转单向链表和双向链表的函数. 要求: 如果链表长度为N,时间复杂度为O(N),额外空间复杂度要求为O(1). 程序: 反转单向链表: public class Node{ public Node(int data){ this.value=data; } public int value; public Node next; } public static Node reverseList(Node node){ Node pre=null; Node next=null; w

数据结构和算法--3链表(单向链表、双向链表、环形单向链表和约瑟夫问题)

链表 链表是以节点的方式来存储 每个节点包含data域和next域,指向下一个节点 链表的各个节点不一定是连续存储 链表分带头节点的链表和没有头节点的链表,根据实际的需求来确定 单向列表 最大特点是可以将物理地址上不连续的数据连接起来,通过指针来对物理地址进行操作,实现增删改查等功能. 单链表分为两种:有头链表和无头链表. 有头节点的增删改查 定义一个单链表的类: //定义一个SingleLinkedList,单链表,管理HeroNode class SingleLinkedList{ //初始

单向链表的建立,添加与删除

/*-------------------------包含头文件------------------------------------*/ #include<stdio.h> #include<stdlib.h> #include<malloc.h> #include<string.h> int count=0; /*-------------------------结构体定义部分------------------------------*/ typed