9

Here is the sample code to go with the question. This API is trying to implement a graph with an adjacency-list representation as an array of Bags indexed by each of vertices in the graph.

public class Graph{

private final int V;          //no. of vertices
private Bag<Integer>[] adj;  // A bag for each vertex to store all adjacent vertices
.
.
.
}

Is there any advantage of using a Bag here over a linked list or a Set. I know that bags are unordered but why go with an unordered list when they don't save us time or space?

deepak
  • 375
  • 1
  • 3
  • 8
  • 2
    I don't think it's a good representation. A graph is usually implemented either by an adjacency matrix or by an adjacency list for every vertex. Adjacency lists should not have duplicates, so there is no real advantage for a `Bag`, and it may introduce duplicates where they shouldn't exist. – RealSkeptic Dec 25 '14 at 18:19

4 Answers4

6

Each data structure can be used under different circumstances:

Set (specifically HashSet) can be list of unordered unique elements. On the other hand, Bags are multisets (unordered collections that may contain duplicate elements).

As for LinkedList they provide easier link manipulation i.e. adding elements at different places, is much easier (constant time).

nitishagar
  • 9,038
  • 3
  • 28
  • 40
  • 4
    @nash_at adding elements at specific places in a linked list is only constant if we already have an iterator to the location. Many times we will have to iterate to the location in linear time. – Steve M Dec 25 '14 at 18:41
  • @SteveM yeah you are correct, that is why I wanted to emphasize on easier link manipulation :) – nitishagar Dec 26 '14 at 04:33
5

A Bag is likely implemented with a binary search tree or hash table, giving us O(log n) or O(1) searches. A linked list is going to give O(n) searches.

A Set only allows unique elements, so if you need to store duplicates you need a Bag. The TreeSet or HashSet in the Java Collections library will give us O(log n) or O(1) searches, respectively.

In general, the Set or Bag interfaces will be more suitable when you often need to perform search or delete operations. If you just need to add to the end of the collection and iterate over it, there wouldn't be much difference.

Steve M
  • 9,296
  • 11
  • 49
  • 98
  • Here is the actual code of [Graph](http://algs4.cs.princeton.edu/41graph/Graph.java.html) data structure since the code is written by very well known professors so, the question holds an important observation. I am also investigating and see if I find something important. – vivek Nov 17 '15 at 10:45
  • `delete` operation on a Bag? Bags do not support removal of items. See https://algs4.cs.princeton.edu/13stacks/ – Janac Meena Mar 12 '20 at 15:23
  • @JanacMeena Some implementations of Bag do support removing elements. – Steve M Jul 10 '21 at 22:49
2

In addition to the other answers, the major difference between a Bag and other unordered data structures i.e. a Set - is that Bags do not support the removal of items once they've been added.

An example use case would be a special logging system where we never intend on deleting past insertions. Or to ensure immutability in highly concurrent systems.

Please see https://algs4.cs.princeton.edu/13stacks/ for an accurate description and comparison of bags against other data structures.

Janac Meena
  • 3,203
  • 35
  • 32
1

Data types like bag, queue, and stack, differ in the specification of which object is to be removed or examined next.

A bag is a collection where removing items isn't supported. Bags purpose is to provide clients with the ability to collect items and then to iterate through the them.

API Bag (Java)

public class Bag<Item> implements Iterable<Item>
    Bag() // creates an empty bag
    void add(Item item)
    boolean isEmpty()
    int size()

Bag.java

import java.util.Iterator;
import java.util.NoSuchElementException;

public class Bag<Item> implements Iterable<Item> {
    private Node<Item> first;
    private int n;

    private static class Node<Item> {
        private Item item;
        private Node<Item> next;
    }

    public Bag() {
        first = null;
        n = 0;
    }

    public boolean isEmpty() {
        return first == null;
    }

    public int size() {
        return n;
    }

    public void add(Item item) {
        Node<Item> oldfirst = first;
        first = new Node<Item>();
        first.item = item;
        first.next = oldfirst;
        n++;
    }

    public Iterator<Item> iterator()  {
        return new LinkedIterator(first);
    }

    private class LinkedIterator implements Iterator<Item> {
        private Node<Item> current;

        public LinkedIterator(Node<Item> first) {
            current = first;
        }

        public boolean hasNext()  { return current != null;                     }
        public void remove()      { throw new UnsupportedOperationException();  }

        public Item next() {
            if (!hasNext()) throw new NoSuchElementException();
            Item item = current.item;
            current = current.next;
            return item;
        }
    }
}
Sabina Orazem
  • 477
  • 4
  • 12
  • Not really, a bag is a multi-set. A set, but it allows multiple duplicates. http://www.cs.umd.edu/class/spring2017/cmsc132-050X/projects/BagsAndDenseTrees/doc/student_classes/Bag.html#:~:text=A%20%22bag%22%20is%20a%20data,an%20element%20to%20the%20bag. – Yan Khonski Dec 03 '22 at 22:24