Class: LinkedList
- Inherits:
-
Object
- Object
- LinkedList
- Includes:
- Enumerable
- Defined in:
- lib/linked_lists/linked_list.rb,
lib/linked_lists/linked_list/node.rb
Overview
An ‘Enumerable` data structure which implements a singly linked list. It’s a proper ‘Enumerable` object like `Array`, `Hash` or `Set`.
Its API has been heavily inspired by ‘Set` and `Array`.
list = LinkedList[1, 2, 3, :foo]
Prepending and shifting items is very fast and happens in *O(1)*.
list = LinkedList[:foo]
list.unshift :bar
list.prepend :baz
list >> 'foobar'
list #=> LinkedList["foobar", :baz, :bar, :foo]
Appending is possible but requires the entire list to be traversed, which gives a time complexity of *O(n)*.
list = LinkedList[:foo]
list.push :bar
list.append :baz
list << 'foobar'
list #=> LinkedList[:foo, :bar, :baz, 'foobar']
Optimal traversing is only possible in one direction, from head (first element) to tail (last element).
To get the length of a linked list, the entire list has to be traversed which happens in *O(n)*.
LinkedList[].size #=> 0
LinkedList[:foo].length #=> 1
LinkedList[:foo, 1, 2, 3].count #=> 4
Getting items by index is possible, but the list needs to be traversed from head to the index, which gives a time complexity of *O(n)*.
list = LinkedList["foobar", :baz, :bar, :foo]
list[0] #=> "foobar"
list.slice(0) #=> "foobar"
list[2] #=> :bar
list[-1] #=> :foo
list[1, 2] #=> [:baz, :bar]
list.slice(1, 2) #=> LinkedList[:baz, :bar]
list[1..3] #=> [:baz, :bar, :foo]
Defined Under Namespace
Classes: Node
Instance Attribute Summary collapse
-
#head ⇒ Node?
The first element of the linked list.
Class Method Summary collapse
-
.[](*elements) ⇒ Object
Create a new ‘LinkedList` with these elements inserted.
Instance Method Summary collapse
-
#+(other) ⇒ self
Returns a new LinkedList which is the result of concatenating this linked list with another linked list or ‘Enumerable`.
-
#[](index, length = nil) ⇒ Object, Array
Get the elements at the specified index.
-
#at(index) ⇒ Object?
Returns the item at the provided index.
-
#clear ⇒ self
Removes all elements from ‘self`.
-
#compact ⇒ self
Returns a new ‘LinkedList` containing all non-nil elements from `self`.
-
#compact! ⇒ self?
Removes all ‘nil` elements from `self`.
-
#concat(enum) ⇒ self
Concatenates this linked list with another linked list or ‘Enumerable`.
-
#concat!(list) ⇒ self
Concatenates this linked list with another linked list.
-
#delete(obj) ⇒ Object
Deletes the first item from ‘self` that is equal to `obj`.
-
#delete_all(obj) ⇒ Object
Deletes all items from ‘self` that are equal to `obj`.
-
#delete_at(index) ⇒ Object?
Deletes the element at the specified index returning that element, or ‘nil` if the `index` is out of range.
-
#delete_if {|An| ... } ⇒ self, ...
Returns self whose entries are those for which the block returns a truthy value.
-
#delete_node(node) ⇒ Node?
Deletes a node from ‘self` that is the same object as the given `node`.
-
#each {|An| ... } ⇒ self, Enumerator
(also: #each_value)
Calls the given block once for each element in linked list, passing the element as a parameter.
-
#each_node {|A| ... } ⇒ self, Enumerator
Calls the given block once for each node in the linked list, passing the node as a parameter.
-
#empty? ⇒ Boolean
Checks if ‘head` is `nil`.
-
#eql?(other) ⇒ Boolean
(also: #==)
Returns true if two linked lists are equal.
-
#filter_map {|An| ... } ⇒ self, Enumerator
Returns a list containing truthy elements returned by the block.
-
#freeze ⇒ self
Freezes the list and its every node.
-
#index(obj = nil) ⇒ Object?
Returns the index of the first object in the linked list such that the object is ‘==` to `obj`.
-
#initialize(enum = nil) ⇒ LinkedList
constructor
A new instance of LinkedList.
-
#insert(index, *objects) ⇒ self
Inserts given objects before or after the element at ‘Integer` index offset; returns `self`.
- #inspect ⇒ String
-
#join(separator = nil) {|| ... } ⇒ String
Time complexity: *O(n)*.
-
#keep_if {|An| ... } ⇒ self, ...
Returns self whose entries are those for which the block returns a truthy value.
-
#last(*args) ⇒ Object, Array
Returns the last element, or the last ‘length` elements, of the linked list.
-
#map {|An| ... } ⇒ self, Enumerator
(also: #collect)
Returns a new ‘LinkedList` which consists of the values returned by the block.
-
#map! {|An| ... } ⇒ self, Enumerator
(also: #collect!)
Replaces the elements with ones returned by the block.
-
#node_at(index) ⇒ Node?
Returns the node at the provided index.
-
#pop(length = nil) ⇒ Object, Array
Removes and returns trailing elements.
-
#push(*objects) ⇒ self
(also: #<<, #add, #append)
Appends the given ‘objects` to `self`.
-
#reject {|An| ... } ⇒ self, Enumerator
Returns a new ‘LinkedList` object whose entries are those for which the block returns a falsey value.
-
#reject! {|An| ... } ⇒ self, ...
Returns self whose entries are those for which the block returns a falsey value.
-
#reverse ⇒ self
Returns a new ‘LinkedList` with the elements of `self` in reverse order.
-
#select {|An| ... } ⇒ self, Enumerator
(also: #filter)
Returns a new ‘LinkedList` object whose entries are those for which the block returns a truthy value.
-
#select! {|An| ... } ⇒ self, ...
(also: #filter!)
Returns self whose entries are those for which the block returns a truthy value.
-
#shift(length = nil) ⇒ Object, Array
Removes and returns leading elements.
-
#size ⇒ Integer
(also: #length)
The number of elements in the list.
-
#slice(index, length = nil) ⇒ Object, self
Get the elements at the specified index.
-
#sublist?(other) ⇒ Boolean
Checks whether ‘self` is a sublist of the provided list `other`.
-
#superlist?(other) ⇒ Boolean
Checks whether ‘self` is a superlist of the provided list `other` (if the `other` list is a sublist of `self`).
-
#tail ⇒ Node?
The last element of the linked list.
- #to_set ⇒ Set
-
#unshift(*objects) ⇒ self
(also: #>>, #prepend)
Prepends the given ‘objects` to `self`.
Constructor Details
#initialize(enum = nil) ⇒ LinkedList
Returns a new instance of LinkedList.
72 73 74 75 76 77 |
# File 'lib/linked_lists/linked_list.rb', line 72 def initialize(enum = nil) @head = nil return if enum.nil? concat(enum) end |
Instance Attribute Details
#head ⇒ Node?
The first element of the linked list. Time complexity: *O(1)*
69 70 71 |
# File 'lib/linked_lists/linked_list.rb', line 69 def head @head end |
Class Method Details
.[](*elements) ⇒ Object
Create a new ‘LinkedList` with these elements inserted.
60 61 62 |
# File 'lib/linked_lists/linked_list.rb', line 60 def [](*elements) new(elements) end |
Instance Method Details
#+(other) ⇒ self
Returns a new LinkedList which is the result of concatenating this linked list with another linked list or ‘Enumerable`.
Time complexity is *O(n + m)*, where n is the length of ‘self` and m is the length of `other`.
835 836 837 |
# File 'lib/linked_lists/linked_list.rb', line 835 def +(other) dup.concat(other) end |
#[](index, length = nil) ⇒ Object, Array
Get the elements at the specified index. Head of the list is ‘0`.
This list in not indexed so the entire list will have to be traversed in the worst case. Time complexity: *O(n)*
219 220 221 |
# File 'lib/linked_lists/linked_list.rb', line 219 def [](index, length = nil) slice_with_enum(::Array, index, length) end |
#at(index) ⇒ Object?
Returns the item at the provided index. This list in not indexed so the entire list will have to be traversed in the worst case. Time complexity: *O(n)*
206 207 208 |
# File 'lib/linked_lists/linked_list.rb', line 206 def at(index) node_at(index)&.value end |
#clear ⇒ self
Removes all elements from ‘self`. Sets the `head` to `nil`.
Time complexity: *O(1)*.
109 110 111 112 |
# File 'lib/linked_lists/linked_list.rb', line 109 def clear @head = nil self end |
#compact ⇒ self
Returns a new ‘LinkedList` containing all non-nil elements from `self`
Time complexity: *O(n)*
745 746 747 748 749 750 751 752 753 754 755 |
# File 'lib/linked_lists/linked_list.rb', line 745 def compact result = self.class.new each do |value| next if value.nil? result << value end result end |
#compact! ⇒ self?
Removes all ‘nil` elements from `self`.
Returns ‘self` if any elements removed, otherwise `nil`.
Time complexity: *O(n)*
764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 |
# File 'lib/linked_lists/linked_list.rb', line 764 def compact! removed = nil prev_node = nil each_node do |node| if node.value.nil? removed = true prev_node, = delete_node_with_prev(prev_node, node.next) next end prev_node = node end return self if removed nil end |
#concat(enum) ⇒ self
Concatenates this linked list with another linked list or ‘Enumerable`.
Time complexity is *O(m)*, where m is the length of given ‘enum`.
714 715 716 717 718 |
# File 'lib/linked_lists/linked_list.rb', line 714 def concat(enum) do_with_enum(enum) { |o| self << o } self end |
#concat!(list) ⇒ self
Concatenates this linked list with another linked list.
This version is faster for two linked lists but more unsafe because concatenating them happens in place by just linking the tail of the first list to the head of the second one. This means that modifying the second list after concatenating it will change the concatenated list as well!
Time complexity is *O(n)*, where n is the length of ‘self`.
732 733 734 735 736 737 738 |
# File 'lib/linked_lists/linked_list.rb', line 732 def concat!(list) raise ::ArgumentError, 'value must be a linked list' unless list.instance_of?(self.class) tail.next = list.head self end |
#delete(obj) ⇒ Object
Deletes the first item from ‘self` that is equal to `obj`. Returns the deleted item, or `nil` if no matching item is found.
Time complexity: *O(n)*
395 396 397 398 399 400 401 402 403 404 405 406 |
# File 'lib/linked_lists/linked_list.rb', line 395 def delete(obj) removed = nil prev_node = nil each_node do |n| next (prev_node = n) unless n.value == obj delete_node_with_prev(prev_node, n.next) return n.value end removed end |
#delete_all(obj) ⇒ Object
Deletes all items from ‘self` that are equal to `obj`. Returns the last deleted item, or `nil` if no matching item is found.
Time complexity: *O(n)*
415 416 417 418 419 420 421 422 |
# File 'lib/linked_lists/linked_list.rb', line 415 def delete_all(obj) removed = nil delete_if do |element| removed = element if element == obj end removed end |
#delete_at(index) ⇒ Object?
Deletes the element at the specified index returning that element, or ‘nil` if the `index` is out of range.
This list in not indexed so the entire list will have to be traversed in the worst case. Time complexity: *O(n)*
455 456 457 458 459 460 461 462 463 464 |
# File 'lib/linked_lists/linked_list.rb', line 455 def delete_at(index) prev_node = nil each_node.with_index do |node, i| return node.value if i == index && delete_node_with_prev(prev_node, node.next) prev_node = node end nil end |
#delete_if {|An| ... } ⇒ self, ...
Returns self whose entries are those for which the block returns a truthy value. Or a new ‘Enumerator` if no block given.
Time complexity: *O(n)*
384 385 386 |
# File 'lib/linked_lists/linked_list.rb', line 384 def delete_if(&block) reject!(&block) || self end |
#delete_node(node) ⇒ Node?
Deletes a node from ‘self` that is the same object as the given `node`. Returns the deleted node, or `nil` if no matching item is found.
Time complexity: *O(n)*
431 432 433 434 435 436 437 438 439 440 441 442 443 444 |
# File 'lib/linked_lists/linked_list.rb', line 431 def delete_node(node) raise ::ArgumentError, 'value should be a node' unless node.is_a?(Node) removed = nil prev_node = nil each_node do |n| next (prev_node = n) unless n == node delete_node_with_prev(prev_node, n.next) return n end removed end |
#each {|An| ... } ⇒ self, Enumerator Also known as: each_value
Calls the given block once for each element in linked list, passing the element as a parameter. Returns an enumerator if no block is given.
Time complexity: *O(n)*
244 245 246 247 248 |
# File 'lib/linked_lists/linked_list.rb', line 244 def each return enum_for(__method__) unless block_given? each_node { |node| yield node.value } end |
#each_node {|A| ... } ⇒ self, Enumerator
Calls the given block once for each node in the linked list, passing the node as a parameter. Returns an enumerator if no block is given.
Time complexity: *O(n)*
260 261 262 263 264 265 266 267 268 269 270 271 |
# File 'lib/linked_lists/linked_list.rb', line 260 def each_node return enum_for(__method__) unless block_given? return unless @head element = @head loop do yield element break if (element = element.next).nil? end self end |
#empty? ⇒ Boolean
Checks if ‘head` is `nil`.
Time complexity: *O(1)*.
119 120 121 |
# File 'lib/linked_lists/linked_list.rb', line 119 def empty? @head.nil? end |
#eql?(other) ⇒ Boolean Also known as: ==
Returns true if two linked lists are equal. The equality of each couple of elements is defined according to ‘#==`.
Time complexity is *O(min(n, m))*, where n is the length of ‘self` and m is the length of `other`.
LinkedList[1, 2] == LinkedList[1, 2] #=> true
LinkedList[1, 2] == LinkedList[1, 2.0] #=> true
LinkedList[1, 3, 5] == LinkedList[1, 5] #=> false
LinkedList[1, 3, 5] == LinkedList[1, 3] #=> false
LinkedList['a', 'b', 'c'] == LinkedList['a', 'c', 'b'] #=> true
LinkedList['a', 'b', 'c'] == ['a', 'c', 'b'] #=> false
853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 |
# File 'lib/linked_lists/linked_list.rb', line 853 def eql?(other) return true if equal?(other) return false unless other.is_a?(self.class) self_node = @head other_node = other.head loop do break if self_node.nil? && other_node.nil? return false if self_node.nil? || other_node.nil? return false if self_node.value != other_node.value self_node = self_node.next other_node = other_node.next end true end |
#filter_map {|An| ... } ⇒ self, Enumerator
Returns a list containing truthy elements returned by the block.
With a block given, calls the block with successive elements; returns a list containing each truthy value returned by the block.
Time complexity: *O(n)*
314 315 316 317 318 319 320 321 322 323 324 325 |
# File 'lib/linked_lists/linked_list.rb', line 314 def filter_map return enum_for(__method__) unless block_given? result = self.class.new each_node do |node| next unless (block_result = yield(node.value)) result << block_result end result end |
#freeze ⇒ self
Freezes the list and its every node.
Time complexity is *O(n)*.
96 97 98 99 100 101 |
# File 'lib/linked_lists/linked_list.rb', line 96 def freeze super each_node(&:freeze) self end |
#index(obj = nil) ⇒ Object?
Returns the index of the first object in the linked list such that the object is ‘==` to `obj`. Time complexity: *O(n)*
If a block is given instead of an argument, returns the index of the first object for which the block returns ‘true`. Returns `nil` if no match is found.
Time complexity: *O(n)*
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/linked_lists/linked_list.rb', line 165 def index(obj = nil) if block_given? each_with_index do |element, i| return i if yield(element) end return end each_with_index do |element, i| return i if obj == element end nil end |
#insert(index, *objects) ⇒ self
Inserts given objects before or after the element at ‘Integer` index offset; returns `self`.
Inserts all given objects before the element at offset index:
a = LinkedList[:foo, 'bar', 2]
a.insert(1, :bat, :bam) # => LinkedList[:foo, :bat, :bam, "bar", 2]
Extends the list if ‘index` is beyond the list (`index` >= `self.size`):
a = LinkedList[:foo, 'bar', 2]
a.insert(5, :bat, :bam)
a # => LinkedList[:foo, "bar", 2, nil, nil, :bat, :bam]
Does nothing if no objects given:
a = LinkedList[:foo, 'bar', 2]
a.insert(1)
a.insert(50)
a.insert(-50)
a # => LinkedList[:foo, "bar", 2]
670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 |
# File 'lib/linked_lists/linked_list.rb', line 670 def insert(index, *objects) index = index.to_int raise ::ArgumentError, 'negative list index' if index.negative? return unshift(*objects) if index.zero? return self if objects.empty? last_node = nil prev_node = nil found_index = false last_index = 0 each_node.with_index do |node, i| last_index = i last_node = node next (prev_node = node) unless i >= index found_index = true prev_node.insert_after(*objects) break end return self if found_index @head = last_node = Node.new if empty? loop do last_index += 1 break if last_index >= index new_node = Node.new last_node.next = new_node last_node = new_node end last_node.insert_after(*objects) self end |
#inspect ⇒ String
908 909 910 |
# File 'lib/linked_lists/linked_list.rb', line 908 def inspect "#<#{self.class}: {#{join(', ', &:inspect)}}>" end |
#join(separator = nil) {|| ... } ⇒ String
Time complexity: *O(n)*
598 599 600 601 602 603 604 605 606 607 |
# File 'lib/linked_lists/linked_list.rb', line 598 def join(separator = nil) result = ::String.new each_node do |node| string_value = block_given? ? yield(node.value) : node.value result << string_value.to_s result << separator if separator && node.next end result end |
#keep_if {|An| ... } ⇒ self, ...
Returns self whose entries are those for which the block returns a truthy value. Or a new ‘Enumerator` if no block given.
Time complexity: *O(n)*
553 554 555 |
# File 'lib/linked_lists/linked_list.rb', line 553 def keep_if(&block) select!(&block) || self end |
#last(*args) ⇒ Object, Array
Returns the last element, or the last ‘length` elements, of the linked list. If the list is empty, the first form returns `nil`, and the second form returns an empty list.
Keep in mind that it’s only possible to traverse this list in one direction from head to tail. So the entire list has to be traversed in order to retrieve the last elements.
Time complexity is *O(2n)*.
151 152 153 |
# File 'lib/linked_lists/linked_list.rb', line 151 def last(*args) to_a.last(*args) end |
#map {|An| ... } ⇒ self, Enumerator Also known as: collect
Returns a new ‘LinkedList` which consists of the values returned by the block. Returns an enumerator if no block is given.
Time complexity: *O(n)*
293 294 295 296 297 298 299 300 301 302 |
# File 'lib/linked_lists/linked_list.rb', line 293 def map return enum_for(__method__) unless block_given? result = self.class.new each_node do |node| result << yield(node.value) end result end |
#map! {|An| ... } ⇒ self, Enumerator Also known as: collect!
Replaces the elements with ones returned by the block. Returns an enumerator if no block is given.
Time complexity: *O(n)*
334 335 336 337 338 339 340 341 342 |
# File 'lib/linked_lists/linked_list.rb', line 334 def map! return enum_for(__method__) unless block_given? each_node do |node| node.value = yield(node.value) end self end |
#node_at(index) ⇒ Node?
Returns the node at the provided index. This list in not indexed so the entire list will have to be traversed in the worst case. Time complexity: *O(n)*
188 189 190 191 192 193 194 195 196 197 |
# File 'lib/linked_lists/linked_list.rb', line 188 def node_at(index) index = index.to_int return each_node.to_a.at(index) if index.negative? each_node.with_index do |node, i| return node if i == index end nil end |
#pop(length = nil) ⇒ Object, Array
Removes and returns trailing elements.
When no argument is given and self is not empty, removes and returns the last element
Keep in mind that the entire list has to be traversed in the worst case to pop an item.
Time complexity: *O(n)*.
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 |
# File 'lib/linked_lists/linked_list.rb', line 511 def pop(length = nil) raise ::TypeError, "no implicit conversion of #{length.class} into Integer" unless length.nil? || length.respond_to?(:to_int) return [] if length&.zero? raise ::ArgumentError, 'negative linked list size' if length&.negative? index = length ? -length : -1 ary = each_node.to_a node = ary[index] || @head prev_node = ary[index - 1] if prev_node.nil? @head = nil else prev_node.next = nil end return node&.value unless length node&.to_list.to_a end |
#push(*objects) ⇒ self Also known as: <<, add, append
Appends the given ‘objects` to `self`.
Time complexity: *O(n)*.
615 616 617 618 619 620 621 622 |
# File 'lib/linked_lists/linked_list.rb', line 615 def push(*objects) return self if objects.empty? @head = Node.new objects.shift if empty? tail.insert_after(*objects) self end |
#reject {|An| ... } ⇒ self, Enumerator
Returns a new ‘LinkedList` object whose entries are those for which the block returns a falsey value. Or a new `Enumerator` if no block given.
Time complexity: *O(n)*
352 353 354 355 356 |
# File 'lib/linked_lists/linked_list.rb', line 352 def reject return enum_for(__method__) unless block_given? select { |o| !yield(o) } end |
#reject! {|An| ... } ⇒ self, ...
Returns self whose entries are those for which the block returns a falsey value. A new ‘Enumerator` if no block given. Or `nil` if no entries were removed.
Time complexity: *O(n)*
540 541 542 543 544 |
# File 'lib/linked_lists/linked_list.rb', line 540 def reject! return enum_for(__method__) unless block_given? select! { |o| !yield(o) } end |
#reverse ⇒ self
Returns a new ‘LinkedList` with the elements of `self` in reverse order. Time complexity: *O(2n)*
277 278 279 280 281 282 283 284 |
# File 'lib/linked_lists/linked_list.rb', line 277 def reverse result = self.class.new reverse_each do |obj| result << obj end result end |
#select {|An| ... } ⇒ self, Enumerator Also known as: filter
Returns a new ‘LinkedList` object whose entries are those for which the block returns a truthy value. Or a new Enumerator if no block given.
Time complexity: *O(n)*
365 366 367 368 369 370 371 372 373 374 |
# File 'lib/linked_lists/linked_list.rb', line 365 def select return enum_for(__method__) unless block_given? result = self.class.new each do |value| result << value if yield(value) end result end |
#select! {|An| ... } ⇒ self, ... Also known as: filter!
Returns self whose entries are those for which the block returns a truthy value. A new ‘Enumerator` if no block given. Or `nil` if no entries were removed.
Time complexity: *O(n)*
565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 |
# File 'lib/linked_lists/linked_list.rb', line 565 def select! return enum_for(__method__) unless block_given? return if empty? removed = false prev_node = nil node = @head next_node = node.next loop do keep = yield(node.value) if keep prev_node = node node = prev_node.next next_node = node&.next else removed = true prev_node, node, next_node = delete_node_with_prev(prev_node, next_node) end break if node.nil? end return unless removed self end |
#shift(length = nil) ⇒ Object, Array
Removes and returns leading elements. When no argument is given, removes and returns the first element. When positive Integer argument ‘length` is given, removes the first `length` elements and returns those elements in a new `Array`.
Time complexity is *O(1)* when no ‘length` is given. Otherwise it’s *O(min(m, n))*, where m is the given ‘length` of elements to be shifted and n is the length of `self`.
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 |
# File 'lib/linked_lists/linked_list.rb', line 477 def shift(length = nil) raise ::TypeError, "no implicit conversion of #{length.class} into Integer" unless length.nil? || length.respond_to?(:to_int) raise ::ArgumentError, 'negative linked list size' if length&.negative? return if empty? unless length prev_head = @head @head = @head.next return prev_head.value end length = length.to_int removed = [] each_node.with_index do |node, i| break if i == length removed << @head.value @head = node.next end removed end |
#size ⇒ Integer Also known as: length
The number of elements in the list. Keep in mind that the entire list needs to be traversed in order to find out it’s length.
Time complexity is *O(n)*.
130 131 132 133 134 135 136 137 |
# File 'lib/linked_lists/linked_list.rb', line 130 def size return 0 if empty? length = 0 each_with_index { |_, i| length = i } length + 1 end |
#slice(index, length = nil) ⇒ Object, self
Get the elements at the specified index. Head of the list is ‘0`.
This list in not indexed so the entire list will have to be traversed in the worst case. Time complexity: *O(n)*
232 233 234 |
# File 'lib/linked_lists/linked_list.rb', line 232 def slice(index, length = nil) slice_with_enum(self.class, index, length) end |
#sublist?(other) ⇒ Boolean
Checks whether ‘self` is a sublist of the provided list `other`. Time complexity is *O(m)*, where m is the length of `other`.
798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 |
# File 'lib/linked_lists/linked_list.rb', line 798 def sublist?(other) return true if equal?(other) raise ::ArgumentError, 'value must be a linked list' unless other.is_a?(self.class) return true if (empty? && !other.empty?) || (empty? && other.empty?) return false if !empty? && other.empty? self_node = @head other_node = other.head at_least_one_equal = false loop do return true if self_node.equal?(other_node) return true if self_node.nil? return false if other_node.nil? if self_node.value == other_node.value at_least_one_equal = true self_node = self_node.next other_node = other_node.next next end return false if at_least_one_equal other_node = other_node.next end true end |
#superlist?(other) ⇒ Boolean
Checks whether ‘self` is a superlist of the provided list `other` (if the `other` list is a sublist of `self`). Time complexity is *O(n)*, where n is the length of `self`.
787 788 789 790 791 |
# File 'lib/linked_lists/linked_list.rb', line 787 def superlist?(other) raise ::ArgumentError, 'value must be a linked list' unless other.is_a?(self.class) other.sublist?(self) end |
#tail ⇒ Node?
The last element of the linked list.
Keep in mind that in order to retrieve it the entire list needs to be traversed.
Time complexity is *O(n)*.
87 88 89 |
# File 'lib/linked_lists/linked_list.rb', line 87 def tail each_node { |node| return node if node.next.nil? } end |
#to_set ⇒ Set
898 899 900 901 902 903 904 905 |
# File 'lib/linked_lists/linked_list.rb', line 898 def to_set set = ::Set.new each do |value| set << value end set end |
#unshift(*objects) ⇒ self Also known as: >>, prepend
Prepends the given ‘objects` to `self`.
Time complexity is *O(1)* if one item is given. Otherwise it’s *O(m)*, where m is the length of given ‘objects`.
634 635 636 637 638 639 640 641 642 |
# File 'lib/linked_lists/linked_list.rb', line 634 def unshift(*objects) objects.reverse_each do |obj| new_node = Node.new obj new_node.next = @head @head = new_node end self end |