среда, 5 августа 2020 г.

Пакет ring в Golang

Пакет ring реализует операции с круговыми списками.

Тип Ring

type Ring struct {
     Value interface{} // для использования клиентом; 
                       // нетронутый этой библиотекой
     // содержит отфильтрованные 
     // или неэкспортированные поля
}

Ring - это элемент кругового списка или кольца. У колец нет начала и конца; указатель на любой элемент кольца служит ссылкой на все кольцо. Пустые кольца представлены как nil указатели на Ring. Нулевое значение для Ring - это одноэлементное кольцо с nil Value.

Функция New

func New(n int) *Ring

New создает кольцо из n элементов.

Метод Do

func (r *Ring) Do(f func(interface{}))

Do вызывает функцию f для каждого элемента кольца в прямом порядке. Поведение Do не определено, если f изменяет *r.

Пример использования Do

package main

import (
    "container/ring"
    "fmt"
)

func main() {
    // Создаем новое кольцо размером 5
    r := ring.New(5)

    // Получаем длину кольца
    n := r.Len()

    // Инициализируем кольцо 
    // некоторыми целочисленными значениями
    for i := 0; i < n; i++ {
        r.Value = i
        r = r.Next()
    }

    // Обходим кольцо и распечатываем его содержимое
    r.Do(func(p interface{}) {
        fmt.Println(p.(int))
    })

}

Вывод:

0
1
2
3
4

Метод Len

func (r *Ring) Len() int

Len вычисляет количество элементов в кольце r. По времени выполняется пропорционально количеству элементов.

Пример использования Len

package main

import (
    "container/ring"
    "fmt"
)

func main() {
    // Создаем новое кольцо размером 4
    r := ring.New(4)

    // Печатаем его длину
    fmt.Println(r.Len())

}

Вывод:

4

Метод Link

func (r *Ring) Link(s *Ring) *Ring

Link соединяет кольцо r с кольцом s, так что r.Next() становится s и возвращает исходное значение для r.Next(). r не должно быть пустым.

Если r и s указывают на одно и то же кольцо, их связывание удаляет элементы между r и s из кольца. Удаленные элементы образуют вложенное кольцо, и результатом является ссылка на это вложенное кольцо (если элементы не были удалены, результатом все равно будет исходное значение для r.Next(), а не nil).

Если r и s указывают на разные кольца, их связывание создает одно кольцо с элементами s, вставленными после r. Результат указывает на элемент, следующий за последним элементом s после вставки.

Пример использования Link

package main

import (
    "container/ring"
    "fmt"
)

func main() {
    // Создаем два кольца, r и s, размера 2
    r := ring.New(2)
    s := ring.New(2)

    // Получаем длину кольца
    lr := r.Len()
    ls := s.Len()

    // Инициализируем r нулями
    for i := 0; i < lr; i++ {
        r.Value = 0
        r = r.Next()
    }

    // Инициализируем s единицами
    for j := 0; j < ls; j++ {
        s.Value = 1
        s = s.Next()
    }

    // Связать кольцо r и кольцо s
    rs := r.Link(s)

    // Обходим объединенное кольцо 
    // и распечатываем его содержимое
    rs.Do(func(p interface{}) {
        fmt.Println(p.(int))
    })

}

Вывод:

0
0
1
1

Метод Move

func (r *Ring) Move(n int) *Ring

Move перемещает n % r.Len() элементов назад (n < 0) или вперед (n >= 0) по кольцу и возвращает этот элемент кольца. r не должно быть пустым.

Пример использования Move

package main

import (
    "container/ring"
    "fmt"
)

func main() {
    // Создаем новое кольцо размером 5
    r := ring.New(5)

    // Получаем длину кольца
    n := r.Len()

    // Инициализируем кольцо 
    // некоторыми целочисленными значениями
    for i := 0; i < n; i++ {
        r.Value = i
        r = r.Next()
    }

    // Перемещаем указатель вперед на три шага
    r = r.Move(3)

    // Обходим кольцо и распечатываем его содержимое
    r.Do(func(p interface{}) {
        fmt.Println(p.(int))
    })

}

Вывод:

3
4
0
1
2

Метод Next

func (r *Ring) Next() *Ring

Next возвращает следующий элемент кольца. r не должно быть пустым.

Пример использования Next

package main

import (
    "container/ring"
    "fmt"
)

func main() {
    // Создаем новое кольцо размером 5
    r := ring.New(5)

    // Получаем длину кольца
    n := r.Len()

    // Инициализируем кольцо 
    // некоторыми целочисленными значениями
    for i := 0; i < n; i++ {
        r.Value = i
        r = r.Next()
    }

    // Обходим кольцо и распечатываем его содержимое
    for j := 0; j < n; j++ {
        fmt.Println(r.Value)
        r = r.Next()
    }

}

Вывод:

0
1
2
3
4

Метод Prev

func (r *Ring) Prev() *Ring

Prev возвращает предыдущий элемент кольца. r не должно быть пустым.

Пример использования Prev

package main

import (
    "container/ring"
    "fmt"
)

func main() {
    // Создаем новое кольцо размером 5
    r := ring.New(5)

    // Получаем длину кольца
    n := r.Len()

    // Инициализируем кольцо 
    // некоторыми целочисленными значениями
    for i := 0; i < n; i++ {
        r.Value = i
        r = r.Next()
    }

    // Обходим кольцо в обратном направлении 
    // и распечатываем его содержимое
    for j := 0; j < n; j++ {
        fmt.Println(r.Value)
        r = r.Prev()
    }

}

Вывод:

4
3
2
1
0

Метод Unlink

func (r *Ring) Unlink(n int) *Ring

Unlink удаляет n % r.Len() элементов из кольца r, начиная с r.Next(). Если n % r.Len() == 0, r остается неизменным. Результат - удаленное подкольцо. r не должно быть пустым.

Пример использования Unlink

package main

import (
    "container/ring"
    "fmt"
)

func main() {
    // Создаем новое кольцо размером 6
    r := ring.New(6)

    // Получаем длину кольца
    n := r.Len()

    // Инициализируем кольцо 
    // некоторыми целочисленными значениями
    for i := 0; i < n; i++ {
        r.Value = i
        r = r.Next()
    }

    // Отключаем три элемента от r, начиная с r.Next()
    r.Unlink(3)

    // Обходим оставшееся кольцо
    // и распечатываем его содержимое
    r.Do(func(p interface{}) {
        fmt.Println(p.(int))
    })

}

Вывод:

0
4
5


Читайте также:


Комментариев нет:

Отправить комментарий