Имя пользователя:
Пароль:
 

Название темы: списки
Показать сообщение отдельно

Аватара для vadimiron

Ветеран


Сообщения: 1864
Благодарности: 120

Профиль | Отправить PM | Цитировать


slaine
Я тут посидел-подумал-пописал, конечно можно написать проше, но мы же не ищем простых путей
Такая структура похожа на смесь деревьев и хеша, поэтому попахивает рекурсивностью
здесь два класса, Node и Hash. Node это отдельные элементы со всеми своими детьми, Hash-это система управления всем этим делом
Node: num-уникальный идентификатор внутри Hash-а, name-имя,children-массив со всеми детками
Hash: table-массив с Node-ами (по сути только с теми, у кого предка нет, все остальные элементы лежат в этих самых элементах, которые находятся на уровне 0(то есть без предка)), counter-счётчик, чтобы определять num для каждого Node

функции:
new_node-для добавления новых Node-ов в Hash, в качестве параметров принимает имя добавляемого и номер его отца, если есть отец
find_node-для поиска Node-а по его имени
show_hash-вроде и так понятно
Вот код:
PHP код: Выделить весь код

class Node
{
    
public $name;
    
public $children;
    
public $num;
    function 
__construct($name,$num)
    {
        
$this->name=$name;
        
$this->children=array();
        
$this->num=$num;
    }
    function 
new_child($child_node)
    {
        
$this->children[]=$child_node;
    }
}
class 
Hash
{
    
public $table;
    
private $counter;
    function 
__construct()
    {
        
$this->table=array();
        
$this->counter=-1;
    }
    function 
new_node($name,$parent_num=FALSE)
    {
        
$this->counter++;
        
$new_node=new Node($name,$this->counter);
        if(
$parent_num===FALSE$this->table[]=$new_node;
        else
        {
            
self::set_child($new_node,$parent_num);
        }
    }
    
private function set_child($child,$parent_num,$table=FALSE)
    {
        if(
$table===FALSE$table=$this->table;
        foreach(
$table as $k=>$v)
        {
            if(
$v->num==$parent_num)
            {
                
$table[$k]->new_child($child);
                return 
TRUE;
            }
            if(!empty(
$v->children))
            {
                if(
self::set_child($child,$parent_num,$v->children)) return TRUE;
                else return 
FALSE;
            }
        }
    }
    function 
find_node($name,$table=FALSE)
    {
        if(
$table==FALSE$table=$this->table;
        foreach(
$table as $v)
        {
            if(
$v->name==$name) return $v->num;
            if(!empty(
$v->children))
            {
                
$ret=self::find_node($name,$v->children);
                if(
$ret) return $ret;
                else return 
FALSE;
            }
        }
    }
    function 
show_hash($table=FALSE,$level=-1)
    {
        if(
$table===FALSE$table=$this->table;
        foreach(
$table as $k=>$v)
        {
            
$level++;
            echo 
str_repeat("-",$level).$v->name."<br>";
            if(!empty(
$v->children))
            {
                
self::show_hash($v->children,$level);
            }
            
$level--;
        }
    }


А вот пример применения:
PHP код: Выделить весь код

$hash=new Hash();
 
$hash->new_node("ass");
$hash->new_node("loop",$hash->find_node("ass"));
$hash->new_node("flip",$hash->find_node("loop"));
$hash->new_node("zxx");
$hash->new_node("flip2",$hash->find_node("loop"));
$hash->new_node("lalala",$hash->find_node("flip"));
 
$hash->show_hash(); 

Кончено, это не самое лучше решение , просто мне хотелось поэксперементировать
Код можно усовершенствовать, используя references, но я их не люблю

Отправлено: 01:44, 29-12-2005 | #4

Название темы: списки