Presentation is loading. Please wait.

Presentation is loading. Please wait.

RED-BLACK TREE SEARCH THE FOLLOWING METHOD IS IN TreeMap.java:

Similar presentations


Presentation on theme: "RED-BLACK TREE SEARCH THE FOLLOWING METHOD IS IN TreeMap.java:"— Presentation transcript:

1

2

3

4

5

6

7

8

9 RED-BLACK TREE SEARCH THE FOLLOWING METHOD IS IN TreeMap.java:

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56 IMPLEMENTATION OF THE HashMap CLASS

57 public HashMap(int initialCapacity, float loadFactor) { if (initialCapacity < 0) throw new IllegalArgumentException ("Illegal Initial Capacity: "+ initialCapacity); if (loadFactor <= 0) throw new IllegalArgumentException ("Illegal Load factor: "+ loadFactor); if (initialCapacity==0) initialCapacity = 1; this.loadFactor = loadFactor; table = new Entry[initialCapacity]; threshold = (int)(initialCapacity * loadFactor); } // constructor

58 FOR THE containsKey, get, put, AND remove METHODS, THE INITIAL STRATEGY IS THE SAME: HASH key TO index ; SEARCH LINKED LIST AT table [index].

59

60

61

62

63

64

65

66

67

68

69

70 TIME ESTIMATES: LET n = count, LET m = table.length. ASSUME THE UNIFORM HASHING ASSUMPTION HOLDS.

71 THE AVERAGE SIZE OF EACH LIST IS n / m

72 FOR THE containsKey METHOD, averageTime S (n, m)  n / 2m iterations. BUT n / m <= loadFactor, A CONSTANT (ASSIGNED IN THE CONSTRUCTOR) SO averageTime S (n, m) < A CONSTANT. averageTime S (n, m) IS CONSTANT.

73

74

75

76 FIELDS IN THE HashIterator CLASS: Entry[ ] table = HashMap.this.table; int index = table.length; START AT BACK Entry entry = null; Entry lastReturned = null; // where the iterator is // currently positioned int type; // 0 for keys, 1 for values, 2 for entries private int expectedModCount = modCount;

77 public boolean hasNext() { while (entry==null && index>0) entry = table[--index]; return entry != null; } // method hasNext

78 public Object next( ) { if (modCount != expectedModCount) throw new ConcurrentModificationException( ); while (entry==null && index>0) entry = table[--index]; if (entry != null) { Entry e = lastReturned = entry; entry = e.next; return type == KEYS ? e.key : (type == VALUES ? e.value : e); } // non-null entry throw new NoSuchElementException( ); } // method next

79

80

81

82

83

84

85

86 214-30-3261 033-51-8000 214-19-9528 819-02-9528 KEYS 819-02-9261 033-30-8262 215-09-1766 214-17-0261 260 null 261 214-30-3261 262 819-02-9261 PART OF table 263 033-30-8262 264 214-17-0261 265 null

87 remove (new Integer (214303261)); 260 null 261 null 262 819-02-9261 263 033-30-8262 264 214-17-0261 265 null containsKey ( new Integer (214170261)) WILL RETURN false BECAUSE INDEX 261 HAS null.

88 SOLUTION: boolean markedForRemoval; put SETS markedForRemoval TO false; remove SETS markedForRemoval TO true.

89 AFTER INITIAL PUTS: 260 null 261 214-30-3261 false 262 819-02-9261 false 263 033-30-8262 false 264 214-17-0261 false 265 null

90 AFTER remove ( new Integer (214303261)); 260 null 261 214-30-3261 true 262 819-02-9261 false 263 033-30-8262 false 264 214-17-0261 false 265 null

91 HERE IS PART OF remove : Entry e = table [index]; if (!e.markedForRemoval && e.hash == hash && key.equals(e.key)) { count--; Object oldValue = e.value; e.markedForRemoval = true; return oldValue; } // if match index = (index + 1) % table.length; OFFSET OF 1

92 THIS SOLUTION LEADS TO ANOTHER PROBLEM: SUPPOSE table.length = 1000 put remove ( put AND remove A TOTAL OF 950 TIMES) … put (REPEATED 40 TIMES) count = 40, SO NO NEED TO RE-HASH

93

94 TOO MANY!

95 SOLUTION: KEEP TRACK OF REMOVALS: private transient int countPlus; // the value of count + the // number of removals since // table.length was last changed public Object put(Object key, Object value) {... if (countPlus >= threshold) rehash( );...

96 private void rehash( ) { … for (int i = 0; i < oldCapacity ; i++) if (oldMap [i] != null && !oldMap [i].markedForRemoval) put (oldMap [i].key, oldMap [i].value); …

97 private void rehash( ) { DON’T REHASH IF … MARKED FOR REMOVAL for (int i = 0; i < oldCapacity ; i++) if (oldMap [i] != null && !oldMap [i].markedForRemoval) put (oldMap [i].key, oldMap [i].value); …

98 CLUSTER: A SEQUENCE OF NON-EMPTY LOCATIONS 260 null 261 214-30-3261 false 262 819-02-9261 false 263 033-30-8262 false 264 214-17-0261 false 265 null KEYS THAT HASH TO 261 FOLLOW THE SAME PATH AS KEYS THAT HASH TO 262, …

99

100 SOLUTION: DOUBLE HASHING, THAT IS, OBTAIN BOTH INDICES AND OFFSETS BY HASHING: index = hash & 0x7FFFFFFF % table.length; offset = hash & 0x7FFFFFFF / table.length; NOW THE OFFSET DEPENDS ON THE KEY, SO DIFFERENT KEYS WILL USU- ALLY HAVE DIFFERENT OFFSETS, SO NO MORE PRIMARY CLUSTERING!

101 TO GET A NEW INDEX: index = (index + offset) % table.length;

102 EXAMPLE: table.length = 11 key index offset 15 41 1981 1651 5835 2752 3523 3082 4734 WHERE WOULD THESE KEYS GO IN table ?

103 index key 047 1 235 358 415 516 6 727 819 9 1030

104 PROBLEM: WHAT IF OFFSET IS MULTIPLE OF table.length ? EXAMPLE: table.length = 11 key index offset 15 41 1981 1651 5835 2752 3523 4734 246422 // BUT 15 IS AT INDEX 4 FOR KEY 246, NEW INDEX = (4 + 22) % 11 = 4. OOPS!

105 SOLUTION : if (offset % table.length == 0) offset = 1; ON AVERAGE, offset % table.length WILL EQUAL 0 ONLY ONCE IN EVERY table.length TIMES.

106 PROBLEM: WHAT IF table.length HAS SEVERAL FACTORS? EXAMPLE: table.length = 20 key index offset 200 1 25 5 1 30 10 1 35 15 1 110 10 5 // BUT 30 IS AT INDEX 10 FOR KEY 110, NEW INDEX = (10 + 5) % 20 = 15, WHICH IS OCCUPIED, SO NEW INDEX = (15 + 5) % 20, WHICH IS OCCUPIED, SO NEW INDEX =...

107 SOLUTION: MAKE table.length A PRIME.

108

109

110


Download ppt "RED-BLACK TREE SEARCH THE FOLLOWING METHOD IS IN TreeMap.java:"

Similar presentations


Ads by Google