Priority Queue with O(1) Insertion Time using Arrays? - java

My code right now has O(N) insertion time, and O(1) removal time. I need to change this around. I am trying to implement O(1) insertion time and O(N) deletion time.
Legend:
nItems = number of items/objects. Initially is set 0.
queArray is my array of long integers.
Here are my two methods. Insertion method does all the sorting work. Delete method just one line - to delete the first element in the array which happens to be the smallest number thanks to our Insert method.
If I were to change insertion time to O(1) would I need to give "sorting task" to remove method? It's a priority queue after all and we have to sort it, otherwise it would be just a regular queue with numbers in random order.
Please, any help would be nice!!!
public void insert(long item) {
int j;
if(nItems==0) // if no items,
queArray[nItems++] = item; // insert at 0
else {
for(j=nItems-1; j>=0; j--) { // start at the end
if( item > queArray[j] ) // if new item larger,
queArray[j+1] = queArray[j]; // shift upward
else // if smaller,
break; // done shifting
} // end for
queArray[j+1] = item; // insert it
nItems++;
} // end else (nItems > 0)
}
public long remove() // remove minimum item
{ return queArray[--nItems]; }

If you want O(1) insertion time and O(N) removal time, simply add new elements unsorted to the end of your internal array, and do an O(N) linear search through your list for removals, shifting the rest of the array down one.
Or for a better implementation, you may want to consider a Fibonacci heap.

I'm not certain you can achieve O(1) insertion time for an array-based priority queue. You could get O(log n) by using a min/max heap structure.
Here's an implementation of that using a List<> internally (but that could be swapped to an array implementation easily enough.
using System;
using System.Collections;
using System.Collections.Generic;
namespace HeapADT
{
public class Heap<T> : ICollection, IEnumerable<T>
where T : IComparable<T>
{
#region Private Members
private readonly List<T> m_Items;
private readonly IComparer<T> m_Comparer;
#endregion
#region Constructors
public Heap()
: this(0)
{}
public Heap( int capacity )
: this( capacity, null )
{}
public Heap( IEnumerable<T> items )
: this( items, null )
{}
public Heap( int capacity, IComparer<T> comparer )
{
m_Items = new List<T>(capacity);
m_Comparer = comparer ?? Comparer<T>.Default;
}
public Heap( IEnumerable<T> items, IComparer<T> comparer )
{
m_Items = new List<T>(items);
m_Comparer = comparer ?? Comparer<T>.Default;
BuildHeap();
}
#endregion
#region Operations
public void Add( T item )
{
m_Items.Add( item );
var itemIndex = Count - 1;
while( itemIndex > 0 )
{
var parentIndex = ParentIndex(itemIndex);
// are we a heap? If yes, then we're done...
if( m_Comparer.Compare( this[parentIndex], this[itemIndex] ) < 0 )
return;
// otherwise, sift the item up the heap by swapping with parent
Swap( itemIndex, parentIndex );
itemIndex = parentIndex;
}
}
public T RemoveRoot()
{
if( Count == 0 )
throw new InvalidOperationException("Cannot remove the root of an empty heap.");
var rootItem = this[0];
ReplaceRoot(RemoveLast());
return rootItem;
}
public T RemoveLast()
{
if( Count == 0 )
throw new InvalidOperationException("Cannot remove the tail from an empty heap.");
var leafItem = this[Count - 1];
m_Items.RemoveAt( Count-1 );
return leafItem;
}
public void ReplaceRoot( T newRoot )
{
if (Count == 0)
return; // cannot replace a nonexistent root
m_Items[0] = newRoot;
Heapify(0);
}
public T this[int index]
{
get { return m_Items[index]; }
private set { m_Items[index] = value; }
}
#endregion
#region Private Members
private void Heapify( int parentIndex )
{
var leastIndex = parentIndex;
var leftIndex = LeftIndex(parentIndex);
var rightIndex = RightIndex(parentIndex);
// do we have a right child?
if (rightIndex < Count)
leastIndex = m_Comparer.Compare(this[rightIndex], this[leastIndex]) < 0 ? rightIndex : leastIndex;
// do we have a left child?
if (leftIndex < Count)
leastIndex = m_Comparer.Compare(this[leftIndex], this[leastIndex]) < 0 ? leftIndex : leastIndex;
if (leastIndex != parentIndex)
{
Swap(leastIndex, parentIndex);
Heapify(leastIndex);
}
}
private void Swap( int firstIndex, int secondIndex )
{
T tempItem = this[secondIndex];
this[secondIndex] = this[firstIndex];
this[firstIndex] = tempItem;
}
private void BuildHeap()
{
for( var index = Count/2; index >= 0; index-- )
Heapify( index );
}
private static int ParentIndex( int childIndex )
{
return (childIndex - 1)/2;
}
private static int LeftIndex( int parentIndex )
{
return parentIndex*2 + 1;
}
private static int RightIndex(int parentIndex)
{
return parentIndex*2 + 2;
}
#endregion
#region ICollection Members
public void CopyTo(Array array, int index)
{
m_Items.CopyTo( (T[])array, index );
}
public int Count
{
get { return m_Items.Count; }
}
public bool IsSynchronized
{
get { return false; }
}
public object SyncRoot
{
get { return null; }
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public IEnumerator<T> GetEnumerator()
{
return m_Items.GetEnumerator();
}
#endregion
}
}

An unsorted linked list sounds like it fits the requirements stated (although they seem a bit silly for most practical applications). You have constant insertion time (stick it at the end or beginning), and linear deletion time (scan the list for the smallest element).

In order to change the insertion time to O(1), you can insert elements in to the array unsorted. You can then create a minPeek() method that searches for the smallest key using a linear search and then call that inside the delete/remove method and delete the smallest key.
Here is how you can achieve this.
public void insert(int item) {
queArray[nItems++] = item;
}
public int remove() {
int removeIndex = minPeek();
if (nItems - 1 != removeIndex) {
for (int i = removeIndex; i < nItems - 1; i++) {
queArray[i] = queArray[i + 1];
}
}
return queArray[--nItems];
}
public int minPeek() {
int min = 0;
for (int i = 0; i < maxSize; i++) {
if (queArray[i] < queArray[min]) {
min = i;
}
}
return min;
}
By doing so your priority queue has O(1) insertion time and delete method has O(N) time.

There is no way to implement a O(1) insertion method and keep you array sorted. If you pass your sorting to the delete method the fast you can do is a O(N log(n)) with quick sort or something.
Or you can do a O(log n) algorithm in the insert method like LBushkin suggest.

Related

How to return the number of elements in a linkedlist

I need to implement the size() function so that it will count the number of elements in a list.
I cannot use a count variable. Should work (given our 'top' node and the constructors [default] setup). I know i have to use a loop but i don't know how to reference indices like i do with arrays.
public class DropOutStack<T> implements StackADT<T> {
private int max;
private LinearNode<T> top;
public DropOutStack(){
max = 10;
top = null;
}
public DropOutStack(int capacity){
setMaxSize(capacity);
}
public DropOutStack(T element){
LinearNode<T> temp = newLinearNode(element);
temp.setNext(top);
top = temp;
max = 10;
}
public DropOutStack(T element, int capacity){
LinearNode<T> temp = newLinearNode(element);
temp.setNext(top);
top = temp;
setMaxSize(capacity);
}
public int size(){
}
public boolean isEmpty(){
if(top == null) return true;
return false;
}
}
DropOutStack list = new DropOutStack("T",4);
System.out.print(list.size());
Should print 1. Since only "T" has been added.
Adding a screenshot of the composition class. I think I have to use a method from there. Interface just declares the push pop peek isempty functions. No code. Not needed for the size() function I believe. This is my first programming class so I hope I gave everything needed to solve this. Please help enter image description here
Something like that will count the elements:
ToIntFunction<LinearNode<T>> counter = (node) -> {
int count = 0;
while( node != null ) {
count++;
node = node.getNext();
}
return( count );
};
…applied in the DropOutStack class size() function:
public int size() {
return( counter.applyAsInt( top ) );
}

How to implement a Least Frequently Used (LFU) cache?

Least Frequently Used (LFU) is a type of cache algorithm used to manage memory within a computer. The standard characteristics of this method involve the system keeping track of the number of times a block is referenced in memory. When the cache is full and requires more room the system will purge the item with the lowest reference frequency.
What would be the best way to implement a most-recently-used cache of objects, say in Java?
I've already implemented one using LinkedHashMap(by maintaining the no. of times objects are accessed) But I'm curious if any of the new concurrent collections would be better candidates.
Consider this case : Suppose cache is full and we need to make space for another one. Say two objects are noted in cache which are accessed for one time only. Which one to remove if we come to know that other(which is not in cache)object is being accessed for more than once ?
Thanks!
You might benefit from the LFU implementation of ActiveMQ: LFUCache
They have provided some good functionality.
I think, the LFU data structure must combine priority queue (for maintaining fast access to lfu item) and hash map (for providing fast access to any item by its key); I would suggest the following node definition for each object stored in cache:
class Node<T> {
// access key
private int key;
// counter of accesses
private int numAccesses;
// current position in pq
private int currentPos;
// item itself
private T item;
//getters, setters, constructors go here
}
You need key for referring to an item.
You need numAccesses as a key for priority queue.
You need currentPos to be able to quickly find a pq position of item by key.
Now you organize hash map (key(Integer) -> node(Node<T>)) to quickly access items and min heap-based priority queue using number of accesses as priority. Now you can very quickly perform all operations (access, add new item, update number of acceses, remove lfu). You need to write each operation carefully, so that it maintains all the nodes consistent (their number of accesses, their position in pq and there existence in hash map). All operations will work with constant average time complexity which is what you expect from cache.
According to me, the best way to implement a most-recently-used cache of objects would be to include a new variable as 'latestTS' for each object. TS stands for timestamp.
// A static method that returns the current date and time as milliseconds since January 1st 1970
long latestTS = System.currentTimeMillis();
ConcurrentLinkedHashMap is not yet implemented in Concurrent Java Collections.
(Ref: Java Concurrent Collection API). However, you can try and use ConcurrentHashMap and DoublyLinkedList
About the case to be considered: in such case, as I have said that you can declare latestTS variable, based upon the value of latestTS variable, you can remove an entry and add the new object. (Don't forget to update frequency and latestTS of the new object added)
As you have mentioned, you can use LinkedHashMap as it gives element access in O(1) and also, you get the order traversal.
Please, find the below code for LFU Cache:
(PS: The below code is the answer for the question in the title i.e. "How to implement LFU cache")
import java.util.LinkedHashMap;
import java.util.Map;
public class LFUCache {
class CacheEntry
{
private String data;
private int frequency;
// default constructor
private CacheEntry()
{}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public int getFrequency() {
return frequency;
}
public void setFrequency(int frequency) {
this.frequency = frequency;
}
}
private static int initialCapacity = 10;
private static LinkedHashMap<Integer, CacheEntry> cacheMap = new LinkedHashMap<Integer, CacheEntry>();
/* LinkedHashMap is used because it has features of both HashMap and LinkedList.
* Thus, we can get an entry in O(1) and also, we can iterate over it easily.
* */
public LFUCache(int initialCapacity)
{
this.initialCapacity = initialCapacity;
}
public void addCacheEntry(int key, String data)
{
if(!isFull())
{
CacheEntry temp = new CacheEntry();
temp.setData(data);
temp.setFrequency(0);
cacheMap.put(key, temp);
}
else
{
int entryKeyToBeRemoved = getLFUKey();
cacheMap.remove(entryKeyToBeRemoved);
CacheEntry temp = new CacheEntry();
temp.setData(data);
temp.setFrequency(0);
cacheMap.put(key, temp);
}
}
public int getLFUKey()
{
int key = 0;
int minFreq = Integer.MAX_VALUE;
for(Map.Entry<Integer, CacheEntry> entry : cacheMap.entrySet())
{
if(minFreq > entry.getValue().frequency)
{
key = entry.getKey();
minFreq = entry.getValue().frequency;
}
}
return key;
}
public String getCacheEntry(int key)
{
if(cacheMap.containsKey(key)) // cache hit
{
CacheEntry temp = cacheMap.get(key);
temp.frequency++;
cacheMap.put(key, temp);
return temp.data;
}
return null; // cache miss
}
public static boolean isFull()
{
if(cacheMap.size() == initialCapacity)
return true;
return false;
}
}
Here's the o(1) implementation for LFU - http://dhruvbird.com/lfu.pdf
I have tried to implement this below LFU cache implementation. Took reference from this -
LFU paper. My implementation is working nicely.
If anyone wants to provide any further suggestion to improve it again, please let me know.
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
public class LFUCacheImplementation {
private Map<Integer, Node> cache = new HashMap<>();
private Map<Integer, Integer> counts = new HashMap<>();
private TreeMap<Integer, DoublyLinkedList> frequencies = new TreeMap<>();
private final int CAPACITY;
public LFUCache(int capacity) {
this.CAPACITY = capacity;
}
public int get(int key) {
if (!cache.containsKey(key)) {
return -1;
}
Node node = cache.get(key);
int frequency = counts.get(key);
frequencies.get(frequency).remove(new Node(node.key(), node.value()));
removeFreq(frequency);
frequencies.computeIfAbsent(frequency + 1, k -> new DoublyLinkedList()).add(new Node(node.key(), node.value()));
counts.put(key, frequency + 1);
return cache.get(key).value();
}
public void set(int key, int value) {
if (!cache.containsKey(key)) {
Node node = new Node(key, value);
if (cache.size() == CAPACITY) {
int l_count = frequencies.firstKey();
Node deleteThisNode = frequencies.get(l_count).head();
frequencies.get(l_count).remove(deleteThisNode);
int deleteThisKey = deleteThisNode.key();
removeFreq(l_count);
cache.remove(deleteThisKey);
counts.remove(deleteThisKey);
}
cache.put(key, node);
counts.put(key, 1);
frequencies.computeIfAbsent(1, k -> new DoublyLinkedList()).add(node);
}
}
private void removeFreq(int frequency) {
if (frequencies.get(frequency).size() == 0) {
frequencies.remove(frequency);
}
}
public Map<Integer, Node> getCache() {
return cache;
}
public Map<Integer, Integer> getCounts() {
return counts;
}
public TreeMap<Integer, DoublyLinkedList> getFrequencies() {
return frequencies;
}
}
class Node {
private int key;
private int value;
private Node next;
private Node prev;
public Node(int key, int value) {
this.key = key;
this.value = value;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
public Node getPrev() {
return prev;
}
public void setPrev(Node prev) {
this.prev = prev;
}
public int key() {
return key;
}
public int value() {
return value;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Node)) return false;
Node node = (Node) o;
return key == node.key &&
value == node.value;
}
#Override
public int hashCode() {
return Objects.hash(key, value);
}
#Override
public String toString() {
return "Node{" +
"key=" + key +
", value=" + value +
'}';
}
}
class DoublyLinkedList {
private int size;
private Node head;
private Node tail;
public void add(Node node) {
if (null == head) {
head = node;
} else {
tail.setNext(node);
node.setPrev(tail);
}
tail = node;
size++;
}
public void remove(Node node) {
if(null == head || null == node) {
return;
}
if(this.size() == 1 && head.equals(node)) {
head = null;
tail = null;
} else if (head.equals(node)) {
head = node.getNext();
head.setPrev(null);
} else if (tail.equals(node)) {
Node prevToTail = tail.getPrev();
prevToTail.setNext(null);
tail = prevToTail;
} else {
Node current = head.getNext();
while(!current.equals(tail)) {
if(current.equals(node)) {
Node prevToCurrent = current.getPrev();
Node nextToCurrent = current.getNext();
prevToCurrent.setNext(nextToCurrent);
nextToCurrent.setPrev(prevToCurrent);
break;
}
current = current.getNext();
}
}
size--;
}
public Node head() {
return head;
}
public int size() {
return size;
}
}
Client code to use the above cache implementation -
import java.util.Map;
public class Client {
public static void main(String[] args) {
Client client = new Client();
LFUCache cache = new LFUCache(4);
cache.set(11, function(11));
cache.set(12, function(12));
cache.set(13, function(13));
cache.set(14, function(14));
cache.set(15, function(15));
client.print(cache.getFrequencies());
cache.get(13);
cache.get(13);
cache.get(13);
cache.get(14);
cache.get(14);
cache.get(14);
cache.get(14);
client.print(cache.getCache());
client.print(cache.getCounts());
client.print(cache.getFrequencies());
}
public void print(Map<Integer, ? extends Object> map) {
for(Map.Entry<Integer, ? extends Object> entry : map.entrySet()) {
if(entry.getValue() instanceof Node) {
System.out.println("Cache Key => "+entry.getKey()+", Cache Value => "+((Node) entry.getValue()).toString());
} else if (entry.getValue() instanceof DoublyLinkedList) {
System.out.println("Frequency Key => "+entry.getKey()+" Frequency Values => [");
Node head = ((DoublyLinkedList) entry.getValue()).head();
while(null != head) {
System.out.println(head.toString());
head = head.getNext();
}
System.out.println(" ]");
} else {
System.out.println("Count Key => "+entry.getKey()+", Count Value => "+entry.getValue());
}
}
}
public static int function(int key) {
int prime = 31;
return key*prime;
}
}
How about a priority queue? You can keep elements sorted there with keys representing the frequency. Just update the object position in the queue after visiting it. You can update just from time to time for optimizing the performance (but reducing precision).
Many implementations I have seen have runtime complexity O(log(n)). This means, when the cache size is n, the time needed to insert/remove an element into/from chache is logarithmic. Such implementations use usually a min heap to maintain usage frequencies of elements. The root of the heap contains the element with lowest frequency, and can be accessed in O(1) time. But to maintain the heap property we have to move an element, every time it is used (and frequency is incremented) inside of the heap, to place it into proper position, or when we have to insert new element into the cache (and so put it into the heap).
But the runtime complexity can be reduced to O(1), when we maintain a hashmap (Java) or unordered_map (C++) with the element as key. Additinally we need two sorts of lists, frequency list and elements lists. The elements lists contain elements that have same frequency, and the frequency list contain the element lists.
frequency list
1 3 6 7
a k y x
c l z
m n
Here in the example we see the frequency list that has 4 elements (4 elements lists). The element list 1 contains elements (a,c,m), the elements list 3 contains elements (k, l, n) etc.
Now, when we use say element y, we have to increment its frequency and put it in the next list. Because the elements list with frequency 6 becomes empty, we delete it. The result is:
frequency list
1 3 7
a k y
c l x
m n z
We place the element y in the begin of the elements list 7. When we have to remove elements from the list later, we will start from the end (first z, then x and then y).
Now, when we use element n, we have to increment its frequency and put it into the new list, with frequencies 4:
frequency list
1 3 4 7
a k n y
c l x
m z
I hope the idea is clear. I provide now my C++ implementation of the LFU cache, and will add later a Java implementation.
The class has just 2 public methods, void set(key k, value v)
and bool get(key k, value &v). In the get method the value to retrieve will be set per reference when the element is found, in this case the method returns true. When the element is not found, the method returns false.
#include<unordered_map>
#include<list>
using namespace std;
typedef unsigned uint;
template<typename K, typename V = K>
struct Entry
{
K key;
V value;
};
template<typename K, typename V = K>
class LFUCache
{
typedef typename list<typename Entry<K, V>> ElementList;
typedef typename list <pair <uint, ElementList>> FrequencyList;
private:
unordered_map <K, pair<typename FrequencyList::iterator, typename ElementList::iterator>> cacheMap;
FrequencyList elements;
uint maxSize;
uint curSize;
void incrementFrequency(pair<typename FrequencyList::iterator, typename ElementList::iterator> p) {
if (p.first == prev(elements.end())) {
//frequency list contains single list with some frequency, create new list with incremented frequency (p.first->first + 1)
elements.push_back({ p.first->first + 1, { {p.second->key, p.second->value} } });
// erase and insert the key with new iterator pair
cacheMap[p.second->key] = { prev(elements.end()), prev(elements.end())->second.begin() };
}
else {
// there exist element(s) with higher frequency
auto pos = next(p.first);
if (p.first->first + 1 == pos->first)
// same frequency in the next list, add the element in the begin
pos->second.push_front({ p.second->key, p.second->value });
else
// insert new list before next list
pos = elements.insert(pos, { p.first->first + 1 , {{p.second->key, p.second->value}} });
// update cachMap iterators
cacheMap[p.second->key] = { pos, pos->second.begin() };
}
// if element list with old frequency contained this singe element, erase the list from frequency list
if (p.first->second.size() == 1)
elements.erase(p.first);
else
// erase only the element with updated frequency from the old list
p.first->second.erase(p.second);
}
void eraseOldElement() {
if (elements.size() > 0) {
auto key = prev(elements.begin()->second.end())->key;
if (elements.begin()->second.size() < 2)
elements.erase(elements.begin());
else
elements.begin()->second.erase(prev(elements.begin()->second.end()));
cacheMap.erase(key);
curSize--;
}
}
public:
LFUCache(uint size) {
if (size > 0)
maxSize = size;
else
maxSize = 10;
curSize = 0;
}
void set(K key, V value) {
auto entry = cacheMap.find(key);
if (entry == cacheMap.end()) {
if (curSize == maxSize)
eraseOldElement();
if (elements.begin() == elements.end()) {
elements.push_front({ 1, { {key, value} } });
}
else if (elements.begin()->first == 1) {
elements.begin()->second.push_front({ key,value });
}
else {
elements.push_front({ 1, { {key, value} } });
}
cacheMap.insert({ key, {elements.begin(), elements.begin()->second.begin()} });
curSize++;
}
else {
entry->second.second->value = value;
incrementFrequency(entry->second);
}
}
bool get(K key, V &value) {
auto entry = cacheMap.find(key);
if (entry == cacheMap.end())
return false;
value = entry->second.second->value;
incrementFrequency(entry->second);
return true;
}
};
Here are examples of usage:
int main()
{
LFUCache<int>cache(3); // cache of size 3
cache.set(1, 1);
cache.set(2, 2);
cache.set(3, 3);
cache.set(2, 4);
rc = cache.get(1, r);
assert(rc);
assert(r == 1);
// evict old element, in this case 3
cache.set(4, 5);
rc = cache.get(3, r);
assert(!rc);
rc = cache.get(4, r);
assert(rc);
assert(r == 5);
LFUCache<int, string>cache2(2);
cache2.set(1, "one");
cache2.set(2, "two");
string val;
rc = cache2.get(1, val);
if (rc)
assert(val == "one");
else
assert(false);
cache2.set(3, "three"); // evict 2
rc = cache2.get(2, val);
assert(rc == false);
rc = cache2.get(3, val);
assert(rc);
assert(val == "three");
}
Here is a simple implementation of LFU cache in Go/Golang based on here.
import "container/list"
type LFU struct {
cache map[int]*list.Element
freqQueue map[int]*list.List
cap int
maxFreq int
lowestFreq int
}
type entry struct {
key, val int
freq int
}
func NewLFU(capacity int) *LFU {
return &LFU{
cache: make(map[int]*list.Element),
freqQueue: make(map[int]*list.List),
cap: capacity,
maxFreq: capacity - 1,
lowestFreq: 0,
}
}
// O(1)
func (c *LFU) Get(key int) int {
if e, ok := c.cache[key]; ok {
val := e.Value.(*entry).val
c.updateEntry(e, val)
return val
}
return -1
}
// O(1)
func (c *LFU) Put(key int, value int) {
if e, ok := c.cache[key]; ok {
c.updateEntry(e, value)
} else {
if len(c.cache) == c.cap {
c.evict()
}
if c.freqQueue[0] == nil {
c.freqQueue[0] = list.New()
}
e := c.freqQueue[0].PushFront(&entry{key, value, 0})
c.cache[key] = e
c.lowestFreq = 0
}
}
func (c *LFU) updateEntry(e *list.Element, val int) {
key := e.Value.(*entry).key
curFreq := e.Value.(*entry).freq
c.freqQueue[curFreq].Remove(e)
delete(c.cache, key)
nextFreq := curFreq + 1
if nextFreq > c.maxFreq {
nextFreq = c.maxFreq
}
if c.lowestFreq == curFreq && c.freqQueue[curFreq].Len() == 0 {
c.lowestFreq = nextFreq
}
if c.freqQueue[nextFreq] == nil {
c.freqQueue[nextFreq] = list.New()
}
newE := c.freqQueue[nextFreq].PushFront(&entry{key, val, nextFreq})
c.cache[key] = newE
}
func (c *LFU) evict() {
back := c.freqQueue[c.lowestFreq].Back()
delete(c.cache, back.Value.(*entry).key)
c.freqQueue[c.lowestFreq].Remove(back)
}

Merge Sort with Strings

I have a linked list in a class named WordNode, which holds the following attributes:
String _word; WordNode _next;
I have another class which is the "actual list" which only holds a reference to the head of the list, the class is called TextList and it receives a String and supposed to put every word of the String SORTED IN THE LIST. For example, for the sentence:
coding in Java is cool.
The linked list would look like:
coding >>> cool >>> Java >>> in >>> is.
The arrows are like pointers to the next node in the list.
I want to first take all the words and put them in a linked list (TextList class) and then make a MERGE SORT to sort the words in the linked list.
What I though of doing is taking a split method to split the list into two lists: "odd" and "evens", which is these methods:
private TextList splitOdds(){
boolean flag=true;
TextList odds=new TextList();
WordNode o=null;
WordNode ptr=_head;
while (ptr.getNext()!=null){
if(flag)
o=new WordNode(ptr.getWord(),o);
ptr=ptr.getNext();
flag=!flag;
}
odds._head=o;;
return odds;
}
private TextList splitEvens(){
boolean flag=true;
TextList evens=new TextList();
WordNode e=null;
WordNode ptr=this._head.getNext();
while (ptr!=null){
if(flag)
e=new WordNode(ptr.getWord(),e);
ptr=ptr.getNext();
flag=!flag;
}
evens._head=e;
return evens;
}
The split does work.
But I don't know where to continue from here. I want to call the split method, recursively and split the list until it is a list of one or two nodes, but I can't figure out how to do that.
Edit: can not use a third class, forhibited by the excercise. Also holding the length of TextList. Only holding number of times each word appears by an attribute on WordNode class.
This is of course assuming that you keep the length of the list at each insertion or deletion. All you have to do is split the list in half like this while keeping the head/root of the original list. You will not even need any intermediary list while implementing your merge sort.
LinkedList LinkedList::split(){
_Node_* p=head, *q=p;
for(int i=0; i<len/2; i++){
q=p;
p=p->next;
}
LinkedList ret;
ret.head=p;
ret.len=len-len/2;
len=len/2;
q->next=NULL;
return ret;
}
IMHO, the concept is wrong. You dont need to use merge-sort here. Try searching for PriorityQueue or actually BinaryHeap in order to solve this task. Secondly, merge sort on linked list is not a good idea since it will not be efficient at all. I think you should totally rework your solution.
NB. Just implement the operation YourLinkedList.getByIndex() for convinience, add the size atribute to hold the number of items in the linked list, then create one more linkedList and perform the bottom-up merge-sort like you would do with a simple array.
Structures:
public class Item {
private String word;
private Item next;
public Item(String word) {
this.word = word;
}
public Item getNext() {
return next;
}
public void setNext(Item next) {
this.next = next;
}
public String getWord() {
return word;
}
public void setWord(String word) {
this.word = word;
}
}
Linked List:
public class LinkedList {
private int size = 0;
private Item first = null;
public void swapFragment(LinkedList list, int from, int to) {
if (from >= 0 && to < size) {
list.get(to-from).setNext(this.get(to+1));
if (from > 0) {
this.get(from-1).setNext(list.get(0));
} else {
this.first = list.get(0);
}
}
}
public void addItem(String word) {
if (first == null) {
first = new Item(word);
} else {
Item item = first;
while (item.getNext() != null) {
item = item.getNext();
}
item.setNext(new Item(word));
}
this.size++;
}
public Item get(int index) {
if (index >= size) {
return null;
} else {
Item item = first;
for(int i = 1; i <= index; i++) {
item = item.getNext();
}
return item;
}
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public String toString() {
Item item = first;
String message = null;
if (item != null) {
message = item.getWord() + " ";
} else {
return null;
}
while (item.getNext() != null) {
item = item.getNext();
message = message + item.getWord() + " ";
}
return message;
}
}
Merge Sort:
public class ListMergeSort {
public void sort(LinkedList list, int lo, int hi) {
if (hi <= lo) {
return;
}
int mid = lo + (hi-lo)/2;
sort(list, lo, mid);
sort(list, mid+1, hi);
merge(list, lo, hi, mid);
}
private void merge(LinkedList list, int lo, int hi, int mid) {
int i = lo;
int j = mid+1;
LinkedList newList = new LinkedList();
for (int k = lo; k <= hi; k++) {
if (i > mid) {
newList.addItem(list.get(j).getWord());
j++;
} else if (j > hi) {
newList.addItem(list.get(i).getWord());
i++;
} else if (list.get(i).getWord().compareTo(list.get(j).getWord()) < 0) {
newList.addItem(list.get(i).getWord());
i++;
} else {
newList.addItem(list.get(j).getWord());
j++;
}
}
list.swapFragment(newList, lo, hi);
}
}
Test Class for Strings:
import org.junit.*;
public class MergeTest {
#Test
public void testWords() {
LinkedList list = new LinkedList();
list.addItem("word");
list.addItem("pipe");
list.addItem("trainer");
list.addItem("stark");
list.addItem("33");
list.addItem("dmitry");
ListMergeSort lms = new ListMergeSort();
lms.sort(list, 0, list.getSize()-1);
}
}
Now you just need to create a class which receives a string as an argument, splits it with String.split() and adds the resulting words into the internal LinkedList datastructure. Then you sort them inside with the merge sort and you get the result.

How do I search for a String in an array of Strings using binarySearch or another method?

Using binarySearch never returns the right index
int j = Arrays.binarySearch(keys,key);
where keys is type String[] and key is type String
I read something about needing to sort the Array, but how do I even do that if that is the case?
Given all this I really just need to know:
How do you search for a String in an array of Strings (less than 1000) then?
From Wikipedia:
"In computer science, a binary search is an algorithm for locating the position of an element in a sorted list by checking the middle, eliminating half of the list from consideration, and then performing the search on the remaining half.[1][2] If the middle element is equal to the sought value, then the position has been found; otherwise, the upper half or lower half is chosen for search based on whether the element is greater than or less than the middle element."
So the prerequisite for binary search is that the data is sorted. It has to be sorted because it cuts the array in half and looks at the middle element. If the middle element is what it is looking for it is done. If the middle element is larger it takes the lower half of the array. If the middle element is smaller it the upper half of the array. Then the process is repeated (look in the middle etc...) until the element is found (or not).
If the data isn't sorted the algorithm cannot work.
So you would do something like:
final String[] data;
final int index;
data = new String[] { /* init the elements here or however you want to do it */ };
Collections.sort(data);
index = Arrays.binarySearch(data, value);
or, if you do not want to sort it do a linear search:
int index = -1; // not found
for(int i = 0; i < data.length; i++)
{
if(data[i].equals(value))
{
index = i;
break; // stop looking
}
}
And for completeness here are some variations with the full method:
// strict one - disallow nulls for everything
public <T> static int linearSearch(final T[] data, final T value)
{
int index;
if(data == null)
{
throw new IllegalArgumentException("data cannot be null");
}
if(value == null)
{
throw new IllegalArgumentException("value cannot be null");
}
index = -1;
for(int i = 0; i < data.length; i++)
{
if(data[i] == null)
{
throw new IllegalArgumentException("data[" + i + "] cannot be null");
}
if(data[i].equals(value))
{
index = i;
break; // stop looking
}
}
return (index);
}
// allow null for everything
public static <T> int linearSearch(final T[] data, final T value)
{
int index;
index = -1;
if(data != null)
{
for(int i = 0; i < data.length; i++)
{
if(value == null)
{
if(data[i] == null)
{
index = i;
break;
}
}
else
{
if(value.equals(data[i]))
{
index = i;
break; // stop looking
}
}
}
}
return (index);
}
You can fill in the other variations, like not allowing a null data array, or not allowing null in the value, or not allowing null in the array. :-)
Based on the comments this is also the same as the permissive one, and since you are not writing most of the code it would be better than the version above. If you want it to be paranoid and not allow null for anything you are stuck with the paranoid version above (and this version is basically as fast as the other version since the overhead of the method call (asList) probably goes away at runtime).
public static <T> int linearSearch(final T[] data, final T value)
{
final int index;
if(data == null)
{
index = -1;
}
else
{
final List<T> list;
list = Arrays.asList(data);
index = list.indexOf(value);
}
return (index);
}
java.util.Arrays.sort(myArray);
That's how binarySearch is designed to work - it assumes sorting so that it can find faster.
If you just want to find something in a list in O(n) time, don't use BinarySearch, use indexOf. All other implementations of this algorithm posted on this page are wrong because they fail when the array contains nulls, or when the item is not present.
public static int indexOf(final Object[] array, final Object objectToFind, int startIndex) {
if (array == null) {
return -1;
}
if (startIndex < 0) {
startIndex = 0;
}
if (objectToFind == null) {
for (int i = startIndex; i < array.length; i++) {
if (array[i] == null) {
return i;
}
}
} else {
for (int i = startIndex; i < array.length; i++) {
if (objectToFind.equals(array[i])) {
return i;
}
}
}
return -1;
}
To respond correctly to you question as you have put it. Use brute force
I hope it will help
public int find(String first[], int start, int end, String searchString){
int mid = start + (end-start)/2;
// start = 0;
if(first[mid].compareTo(searchString)==0){
return mid;
}
if(first[mid].compareTo(searchString)> 0){
return find(first, start, mid-1, searchString);
}else if(first[mid].compareTo(searchString)< 0){
return find(first, mid+1, end, searchString);
}
return -1;
}
Of all the overloaded versions of binarySearch in Java, there is no such a version which takes an argument of String. However, there are three types of binarySearch that might be helpful to your situation:
static int binarySearch(char[] a, char key);
static int binarySearch(Object[] a, Object key);
static int binarySearch(T[] a, T key, Comparator c)

Correct heap implementation in a priority queue

My issue is more semantic than functional, As the code does seem to implement the deQueue and enQueue functions correctly.
The reheapDown and reheapUp functions are being used incorrectly, And i believe the issue lies in my heap function
package priqueue;
public class Hosheap{
private Patient[] elements;
private int numElements;
public Hosheap(int maxSize)
{
elements= new Patient[maxSize];
numElements=maxSize;
}
public void ReheapDown(int root,int bottom)
{
int maxChild;
int rightChild;
int leftChild;
leftChild=root*2+1;
rightChild=root*2+2;
if (leftChild<=bottom)
{
if(leftChild==bottom)
maxChild=leftChild;
else
{
if(elements[leftChild].getPriority() <= elements[rightChild].getPriority())
maxChild=rightChild;
else
maxChild=leftChild;
}
if(elements[root].getPriority()<elements[maxChild].getPriority())
{
Swap(root,maxChild);
ReheapDown(maxChild,bottom);
}
}
}
public void ReheapUp(int root,int bottom)
{
int parent;
if(bottom>root)
{
parent=(bottom-1)/2;
if(elements[parent].getPriority()<elements[bottom].getPriority())
{
Swap(parent,bottom);
ReheapUp(root,parent);
}
}
}
public void Swap(int Pos1, int Pos2)
{
Patient temp;
temp = elements[Pos1];
elements[Pos1]=elements[Pos2];
elements[Pos2]=temp;
}
public Patient getElement(int e)
{
return elements[e];
}
public void setElement(Patient p, int n)
{
elements[n]=p;
}
}
The idea is to rearrange a simple priority queue system so when a patient object is removed, ReheapUp or down correctly rearranges the queue, Which the code does not accomplish. Should i also include the priority queue code, Or is this already too lengthy?
I am using NetBeans IDE 6.0.1, If that helps.
Depending on your usage requirements, the answer relating to TreeSets will most probably do what you want.
However if you really need a queue, as opposed to a sorted collection, then the inbuilt PriorityQueue may be of use.
Not exactly answering your question, but with Java you may want to look into the built-in Collection classes. You can get priority queue behavior but using a TreeSet (a type of ordered-set) and implementing a custom Comparator for Patient instances. Depending what you're trying to achieve, this may be preferable. It would look something like this:
In Patient.java ...
class Patient implements Comparator {
...
public int compareTo(Patient other) {
return getPriority() > other.getPriority() ? 1 : 0;
}
Then in the place you want to use the queue
Set<Patient> queue = new TreeSet<Patient>();
queue.add(p1);
queue.add(p2);
//traverse in order of priority
for(Patient p : queue) {
doStuff();
}
Here is a simple implementation of a PriorityHeap. I coded it up pretty quick so it may have some flaws but I have implemented the pushUp() and pushDown() logic.
import java.util.Random;
public class Heap {
private Double[] data;
private int lastItem;
public Heap(int initialSize) {
// to simplify child/parent math leave the first index empty
// and use a lastItem that gives us the size
data = new Double[initialSize];
lastItem = 0;
}
public void insert(Double d) {
// double size if needed
// should have a matching shrink but this is example code
if (lastItem + 1 >= data.length) {
Double[] doubled = new Double[data.length * 2];
System.arraycopy(data, 0, doubled, 0, data.length);
data = doubled;
}
data[lastItem + 1] = d;
lastItem++;
pushUp(lastItem);
}
public void pushDown(int index) {
if (lastItem > 1) {
int leftChildIndex = index * 2;
int rightChildIndex = leftChildIndex + 1;
// assume that neither child will dominate (in priority)
// the item at index
int indexToPromote = index;
// there may not be a left child
if (leftChildIndex <= lastItem) {
Double leftChild = data[leftChildIndex];
Double tmp = data[index];
if (tmp.compareTo(leftChild) < 0) {
indexToPromote = leftChildIndex;
}
// there might not be a right child
if (rightChildIndex <= lastItem) {
Double rightChild = data[rightChildIndex];
tmp = data[indexToPromote];
if (tmp.compareTo(rightChild) < 0) {
indexToPromote = rightChildIndex;
}
}
}
// did either child dominate the item at index
// if so swap and push down again
if (indexToPromote != index) {
swap(index, indexToPromote);
pushDown(indexToPromote);
}
}
}
public void pushUp(int index) {
if (index > 1) {
// equivalent to floor((double)index/2.0d);
// if item at index is greater than its parent
// push the item up to until if finds a home
int parentIndex = index >>> 1;
Double parent = data[parentIndex];
Double item = data[index];
if (item.compareTo(parent) > 0) {
swap(parentIndex, index);
pushUp(parentIndex);
}
}
}
public Double removeTop() {
// assume size is zero then examine other cases
Double top = null;
if (lastItem > 1) {
// save the top item and take the bottom item and place it
// at the top the push the new top item down until it
// finds a home
top = data[1];
Double bottom = data[lastItem];
lastItem--;
data[1] = bottom;
pushDown(1);
} else if (lastItem == 1) {
top = data[1];
lastItem--;
}
return top;
}
public int size() {
return lastItem;
}
private void swap(int index1, int index2) {
Double temp = data[index1];
data[index1] = data[index2];
data[index2] = temp;
}
public static void main(String[] args) {
Heap heap = new Heap(4);
Random r = new Random();
for (int i = 0; i < 100000; i++) {
Double d = Double.valueOf(r.nextDouble() * 100.0d);
heap.insert(d);
}
double max = Double.MAX_VALUE;
while (heap.size() > 0) {
Double top = heap.removeTop();
if (top.doubleValue() > max) {
System.out.println("bad ordering...");
}
max = top.doubleValue();
System.out.println(max);
}
System.out.println("done...");
}
}

Categories

Resources