-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathData-Structures_Lecture-Notes.txt
More file actions
2077 lines (1763 loc) · 70 KB
/
Copy pathData-Structures_Lecture-Notes.txt
File metadata and controls
2077 lines (1763 loc) · 70 KB
1
2
3
4
5
6
7
8
9
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
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
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
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
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1/15/14 - Data Structures and Algorithms Lecture 1, Memory Part 1
HW 1 will be posted on Friday
Integers in C++
Computers store integers in binary form.
Decimal = Binary
0 = 0
1 = 1
7 = 111
87 = 1010111
For Binary numbers, a 1 in the last place in 2^0,
and a 1 in next to last place is 2^1
and so forth. All powers of 2.
Binary 1010111 = 1*2^0 + 1*2^1 + 1*2^2 + 0*2^3 + 1*2^4 + 0*2^5 + 1*2^6
= 1 + 2 + 4 + 16 + 64 = decimal 87.
Each of those 0 or 1 binary digits take up 1 bit in memory. one bit is the tiniest amount of memory we can use, because it can only store 0 or 1
(or equivalently, false or true). Since bits are so tiny, we often talk about bytes instead; a byte is equal to 8 bits stuck together, or a series of 8
zeros and ones.
In my VM, integers take up 32 bits of memory, or 4 bytes.
If you wanted to find this info out for your machin, you could use the sizeof command:
cout << "integer size = " << sizeof(int) << " bytes." << endl;
Remember that integers have a max and min size, too.
For my VM, the min is -2147483648 and the max is 2147483648. You can find this
(which may differ with your computer and C++ version) out by putting: #include <limits>
at the top of your code and including a line or 2 like:
cout << "min: " << numeric_limits<int>::min() << endl << "max: " << numeric_limits<int>::max() << endl;
These limits come from having only 32 bits available to hold the data.We use 1 bit to store the sign of the integer. That leaves use 31 bits to use for binary digits.
If you compute 2^31, you get 2147483648 (which is the size of the largest negative integer we can store.)
If you compute 2^31 - 1, you get 2147483647 (which is the largest positive integer we can store; we get one less digit for the positive range
because we also have to store the integer 0).
In other words, the memory space for an integer determines what range of numbers that integer is allowed to have.
When integers 'roll over' from a large positive value to a large negative value or vice versa, it's a direct consequence of this 32-bit limit.
Full disclosure; computers actually store integers a little differently than this, but we'll skip the details
-
Clicker: What is the max value of an integer of 8 bytes can store (C++ longs)? 2^63 - 1.
Clicker: What is the min value of an integer of 8 bytes can store (C++ longs)? -(2^63)
Clicker: What is the max value that an unsigned integer of 8 bytes can store (C++ unsigned longs, always >= 0)? 2^64 - 1
Clicker: What is the min value that an unsigned integer of 8 bytes can store (C++ unsigned longs, always >= 0)? 0
Here's a simple function that makes one integer variable called a.
Void example1()
{
int a = 5;
}
The compiler sees the int a and recongnizes this as an integer variable. Like you, the compiler knows how much memory an integer can take up.
Integers at Compile Time
The compiler reserves that memory for a using a local array of memory (called the stack).
It's in 8-bit blocks, and showing you hexadecimal addresses of some of the blocks.
After the compiler sees the line int a = 5; it reserves a spot for that integer a on this stack of memory and writes the 5 into this spot (in binary).
If each slot is a byte, this int will take up 4 slots. the os makes sure that no other stuff gets written into that location, as long as it exists.
1-17-14 - Memory part 2
Integers at Compile Time
void example1()
{
int a = 5;
}
At the end of our function, just at the closing bracket }, the int a gets destroyed.
Destroying it means that we no longer keep that memory reserved on the stack for a.
Now other variables can be written into a’s former slot in the memory stack. We can’t predict exactly when this will happen, but it’s only a matter of time before
something else writes data over this slot
voic example2()
{
int a = 5;
cout << a << endl;
}
When it runs , this code prints out the crrent value of a in memory. That's 5.
void example3()
{
int a = 5;
cout << &a << endl;
}
The code prints out the current addres where a is stored in the stack memory.
We get the address of a, instead of its value, by putting an ampersand in front (&a). Notice that this address is one of those hexadecimal numbers.
From this example, you can deduce that any variable in C++ also knows where it lives in memory.
void example4()
{
int a = 5;
int* a_ptr = &a;
}
This code makes a separate variable called a_ptr to store the address of a. Again, we get the address bu using the & (called by reference) sign in front of the variable.
This a_pt is a pointer to a. A pointer stores an address in memory where a variable is living. To make a pointer to an inte, we need to add the * to the int type when
we declare it. It's easy to misplace & and * at first.
void example6()
{
int a = 5;
int* a_ptr = &a;
a = a + 1;
}
We can still change a in the normal way, as in the last line aboe, where it becomes 6;
void example7()
{
int a = 5;
int* a_ptr = &a;
*a_ptr = *a_ptr + 1; // a is now 6
}
We can change a by derefercing a_ptr, and we get that by saying *a_ptr.
Dereferencing means that we find the address that a_ptr stored there. (it's a little extra work.)
void example8()
{
int a = 5;
int* a_ptr = &a;
a++; // a becomes 6
(*a_ptr)++; // a becomes 7
}
This code is similar to example 6 and 7. Firsy we use the ++ operator to increas a by 1, rather than doing a direct addition like + 1.
And then we dereference a_ptr to get a and increase that by 1 again, using the ++ operator.
Now you can see how we can change a’s value using either its name or its address.
void example9()
{
int b[4];
b[0] = 1;
b[1] = 2;
b[2] = 4;
b[3] = 8;
}
We can make a variable that’s an array of integers, instead of one single integer. This code is telling the compiler to find room for 4 integers (that’s what the b[4] does).
For arrays, tyhe compiler stores each integer in adjacent locations in memory. After the line int b[4];,
it reserves four integer size blocks, one right after the next, for this array.
Then we can assign to any of those 4 integers, from b[0] to b[3]. Note that arrays in C++ count from 0, not from 1.
An array like b, which gets declared with a size in the square brackets ([]), is stuck at its starting size forever.
We can change the integers in b[0] through b[3], but we can't change b's size from 4 to something like 10 once we build it with 4 slots.
void example5{}
{
int b[4];
b[4] = 5;
}
Segementation Fault. Outside bounds of the array.
Floating Point numbers
A 4-byte (single precision) floating point numkber uses:
1 bit for the sign,
8 bits for the exponent, and
23 bit for the binary digits.*
An 8byte (double precision) floating point number uses:
1 bit for the sign,
11 bits for the exponent, and
52 bits for the binary digits.*
* To a first approximation, anyway. Take 2400 to learn the details.
C++ offers you the choice between floats and doubles.
Floats in the VM
Take up 32 bits of memory, or 4 bytes.
Smallest magnitude: 1.17549e-38
Largest magnitude: 3.40282e+38
Doubles in the VM
Take up 64 bits of memory, or 8 bytes.
Smallest magnitude: 2.22507e-308
Largest magnitude: 1.79769e+308
Like integers, computers store floating point numbers in binary form. Consider these little numbers:
Decimal: 0, 0.5, 0.25, 0.125
Binary: 0, 0.1, 0.01, 0.001
For binary numbers,
a 1 in the first place after the decimal (.) is 2-1,
and a 1 in the next place is 2-2,
and so forth. All still powers of 2.
Some fimilar numbers don't work out nicel in binary:
Decimal: 0, 0.1, 0.333... (1/3), 0.2
Binary: 0, 0.000110011..., 0.010101..., 0.00110011...
1/22/14 - Data Structures and Algorithms Memory Part 3
HW1 due Feb 2, Read p.117 - 133 (Skip Recursive Part) for HW1, Skim p.47-64 for description of general bags
Floating Point Numbers
Like integers, computers store floating point numbers in binary form. Consider these little numbers:
Decimal: 0, 0.5, 0.25, 0.125
Binary: 0, 0.1, 0.01, 0.001
For binary numbers,
a 1 in the first place after the decimal (.) is 2-1,
and a 1 in the next place is 2-2,
and so forth. All still powers of 2.
Some fimilar numbers don't work out nicel in binary:
Decimal: 0, 0.1, 0.333... (1/3), 0.2
Binary: 0, 0.000110011..., 0.010101..., 0.00110011...
EX: 0.0625 = 0.0001 in Binary
EX: 0.375 and 0.75 does not have binary infinite repeats.
Arrays
void bubbleSort(int theArray[], int n)
Suppose you have to write code that sorts an arrya of n integers, like the one above. This is a normal thing to do in this class later on. (Don't worry about
the specifics of sorting yet.)
Now, suppose you want to adapt this code to sort unsigned ints, or doubles. Normally, you would, need to write 3 different versions of the sorting
code to sort these 3 different types of numbers (int, double, or unsigned int). Yuck.
Template Class Sorting
template<class ItemType>
void bubbleSort(ItemType theArray[], int n)
In C++, instead of tying ourselves down to a type, we can define a generic data type (ItemType) and write our code to operate on this ItemType.
Note that this lets us write the sorting code exactly once!
When we run this code in a main program, we specify the actual data types in place of the generic ItemType:
int main(){
string a[5] = {"Z","X","P","K","F"};
bubbleSort(a,5);
int b[2] = {4, -31}
bubbleSort(b,2);
double c[3] = {8.6, 8.4, 8.3}
bubbleSort(c,3);
}
To be a valid ItemType, the base data type must know how to do cpomparasions like less than (<). That allows use to sort array of strings, or ints, or doubles, or unsigned ints.
So any base type with a < operator will be ok here. (This constraint happens because we assume that bubbleSort's using < to do the sorting.)
Compiling Generic Class
template <class ItemType>
void bubbleSort(ItemType theArray[], int n)
{
...
ItemType i[3];
}
If we compile the C++ code that has the main() function, anf that main() C++ code includes the template C++ code (via #include),
then the template code will compile along with the main code.
For HW1, which is a template class, you do something similar: compile ArrayBagTester
C++ Classes
Classes can capture more complicated behavior
Describe a video game character
HP? $? Items? Lives? Location? Destination?
Level of a video game
Map, doors, walls, monsters, traps, goodies
Interactions
What if another npc is in the same area? or finds a goodie?
1-23-14 -
C++ Vars to arrays to struct
You've seen how single varibles (int, double) work and how arrays of those vars work.
You've seen generic vars (ItemType) work singly and in arrays.
To describe more complex problems, we can stick a bunch of vars together into something called a struct.
For instance, a student in 2270 could be described using her name (a string), ID number (an int), and course grade (double)
studen s;
s.name = "Zorro";
s.id = 800292663;
s.grade = 0.75;
Structs are still not ideal, though. This all looks ok, but how about those member variables now?
s.name = "~%6*!";
s.id = -5;
s.grade = -900;
We can't just let people set these values to anything.
What we'd like better is for the struct to have member functions that make sure its memver variables are set to correct values.
How would you check if a student id is a valid numver?
How would you check if the student name is valid?
A struct that includes these members functions is called a class.
Big idea here:
Consider for a moment the relationship between a TYPE AND AN INSTANCE. One example of a type is an int (which decribes a set of possible integer numbers).
int a = 5;
int b = -2212
Your classes, like ArrayBag, are also types; They're just bigger and more complicated types than integes, booleans, or other 'primitive' types in programming languages.
When you classes construct new objects:
ArrayBag<int> oscar;
Those objects you're making are isntances whose type is your class. oscar's just one of all the possible ArraysBags in the world you could have created here.
Class instances are called objects.
Designing Classes are hard. We'll start out with a somple class, called a bag.
Bag class: stores a collection of things
unsorted, for nw
finite capacity, for now
Bag knows how to:
create itself, empty itself, add items, remove items, list all contents, count contents, tell item present in contents, tell how many copies
Notice that nothing in the bag description is specific to C++: this is just a list of things we expect.
How we decide to program those baggy behaviors is much more specific, because we have to commit to a particular way of writing bags.
You know that a list of behaviors for a class, at the highest level, is called an interface. How we program those behaviors specifically is called the class implementation.
What is so important about this distinction?
Interfaces are like contracts you make with the user of your code. You promise, for example, that bags will store items and not forget them.
Implementation is considered the programmer's private business. As long as user thinks
Interface: BagInterface
1-27-14
Read Pg. 31-46 on C++ Classes
HW1 due Sunday.
Function Parameters by Reference
void fun1(int bobo){ bobo *= 2;}
void fun2(int& bobo){ bobo *= 2;}
// void fun3(const int& bobo){ bob *= 2;} // Doesn't work, trying to change the value of bobo when it must remain constant
void fun3(const int& bobo){ cout << " I'm bobo " << bobo << endl; }
int main()
{
int homeslice = 6;
fun1(homeslice); // Homeslice is copied to fun1, and the copy doubles.
cout << homeslice << endl; // No change, original homeslice abides...
fun2(homeslice); // Address of homeslice is copied to fun2 and value at address is doubled
cout << homeslice << endl; // Homeslice is now doubled
fun3(homeslice);
}
Passing in an address to a variable can befaster than passing a copy. But passing in an address also risks exposing the variable to changes.
If we pass the address in as a constant reference, we get the speed and the protection for our variable:
void fun3(const int& bob)
The compiler will actually refuse to build this code at all, because it's breaking the promis (that we made with a const int&)
As long as our fun3 code does not change bobo, it will compile and run just fine.
Class, Array, Vars, Structs
Single Variables, Arrays of Variables, Structs (A bunch of different variables, stuck together to make a new data type),
Classes (With different Variables, but now with member functions to change theme in proper ways.)
Types of Instances
We also talkeed about the relationship between types and instance. The type of a var determines the set of values that each varible instance can have.
Below, the types are double and bool, and the instance are n1 and done.
double n1 = 1/3.0; // 0.3333... is allowed
bool done = false; // only 2 values allowed here
Both C++ and Java are fairly strict about types, especiallt when assigning or converting between types
Exception is generic data types (ItemType)
When we make a var whose type is a class, like:
ArrayBag<string> papas_brand_new_bag;
We can think of the class ArrayBag as being a type and the varible papa as being an instance of the ArrayBag class.
But the convetion dicatates that we usually call the var an object if its type is a class.
So types define instance and classes define objects. It's the same relationship, with different names.
Bag Class Constructor
Makes a new empty bag, initializes it. Check ArrayBag.h and notice that the item array is built.
Make a new empty
Bag Size Functions
getCapacity: returns the current capacity of the bag
getCurrentSize: returns the current number of items within the bag.
isEmpty:
if(itemCount == 0) return true;
else return false;
or..
return(itemCount == 0);
1-29-13 -
Const Functions
Notice that several of the member functions are makred const at the end:
bool ArrayBag<ItemType>::isEmpty() const
These functions are promising not to change the member variable of the bag. Why can they do that?
We do this to make our code safer; accidental changes to the bag get recognized and stopped at compile time.
Notice that other member functions have const input parameters:
What are we promising here? The item we add or remove must not change. (The bag changes, but the item just gets put into the items array.)
Again, this protects against programme errors.
Adding Items
bool ArrayBag<ItemType>::add (const ItemType& newItem)
{
Empty Bag of ints, Default_Capacity = 6, itemCount = 0,
Adds an item, itemCount becomes 1,
}
Can we generalize this to any available slot in the Bag?
items[?] = newItem;
itemCount++;
return true;
Can we do it all in one line? Yes...
items[??] = newItem;
return true;
What if the Bag is full?
Add nothing and return false
Segmentation Faults?
Check those indexes! Count from 0.
items[itemCount++] = newItems;
items[++itemCount] = newItems;
Find Items
How can we tell if the Bag does not contain an item?
If we assume
Removing Items
items[q] = items
1-31-14
Removing Items
If the bag were an ordered collection of items, what would be bad about this gap filling plan?
How would we preserve order while removing item in the bag, if we had to? (Not in HW1 or HW2)
How much work does preserving the order take, compared to what we did in the previous slides?
What would we have to watch out for here?
Listing Items
Create an empty vector (another array-like template class in C++)
vector<ItemType> itemList;
Write a loop: for each item in the item array, add it to the itemList vector using a line like this ( with no ?)
itemList.pushback(items[?]);
Seems a little redundent, no?
We using an array to store data anway
Later, when you write a B-tree container class, this routine will let you make a list from its item even
if they're not stored in a linear way; then it will seem more useful
How do we decide if 2 bags were equal?
Two bags, containing the same amount of items of the same things (just in different order), are the same.
Pointer
void ex8()
{
int a = 5; // Integer
int* a_ptr = &a; // Pointer to Integer
a++; // a + 1
(*a_ptr)++; // a + 1
a_ptr++; // ?!
}
In C++, you can increment pointer addresses using + (or decrement them with -)
int* c = new int[10];
for(int q = 0; q < 10; q++)
c[q] = q;
count << c[5] << endl; // prints 5
count << c[0] + 5 << endl; // also 5
count << c[9] - 4 << endl; // also 5
Specify: Where to start copying, where to stop copying, and destination
int* c = new int[10];
for(int q = 0; q < 10; q++)
c[q] = q; // c: 0 1 2 3 4 5 6 7 8 9
int* d = new int[10];
copy(c, c+5, d); // d: 0 1 2 3 4
copy(c, c+5, d+5); // d: 0 1 2 3 4 0 1 2 3 4
The new command
You can create vars in place other than the local memory... like the heap. you use the new command to do this.
// Define an integer equal to -8 on the heap
// Make a hold the address of this -8
int* b = new int(-8);
Notice, here, that the var with the value of -8 has no name. We only have a pointer to this value, which is a.
void lecture_8_ex_4()
{
int a = -4;
int* b = new int(-8);
}
The nameless -8 that lives on the heap, however, is not destroyed.
Look heap var like this this uses up memory; we sometimes call it a memory leak.
We could rewrite this example so it didn;t lose the pointer to the -8 but instead returned that pointer:
int* ex5()
{
int* b = new int(-8);
return b;
}
Since we return the pointer to the -8 here,
We could rewrite this example so it passes the pointer by reference:
void ex6(int* &8)
{
}
Delete Command
To give back a heap of var memory, we use the delete command:
int* = new int(-8);
delete a;
int* nummies = new int[10];
delete [] nummies;
HW2
In the next hw, we'll make the bag expandable, so it can upsize as needed to hold more items.
First big chance:
ItemType items[DEFAULT_CAPACITY];
becomes
ItemType* items;
So items becomes a pointer to an (as of yet) array of items
Second change: your constructor
Your constructor must make the array, using new:
items = new ItemType[myCapacity];
After this, items is a pointer to an array on the heap.
This means that items is the address of the firsy item in the array.
Your constructor also need to keep track of
delete [] items;
4th: You will need to add a new method clled resize() to the bag. When you items array gets full, this m ethod will:
Make a new item array, twice as big as the old one
Copy all the items from the old items array to the new items array
Delete the old items array
set items = new item array
update myCapacity to the new array size.
2/3/2014
#include <stdio.h>
#include <stdlib.h>
int main()
{
return EXIT_SUCCESS;
}
public class identifier
{
public:
private:
}
Public
Private
Bit
Byte
Shallow Copy
A pointer that references the same instance within an memory.
Deep Copy
A seperate instance that is within it's own reservation in memory.
Stack
Statically Addressible Memory
Student Peter("Peter", 1);
Heap
Dynamically Addressible Memory
new command
ex: Student Pete = new Student("Peter", 1);
Student array = new student[2];
2-5-14
HW 2 due weekend, read pg.152-154, 178-184 on Bag resizing
Void ex8()
{
int a = 5;
int* a_ptr = &a;
a++;
(*a_ptr)++;
a_ptr++;
}
int* c = new int[10];
// add a val for array parts
cout << c[5] << endl;
You can create vars in place other than the local memory like the heap. You use the new command to do this.
// Define an int(-8);
int* b = new int(-8);
delete b;
To give back a heap memory, we use the delete command, for array we add [] to the delete command
int* c = new int[8];
delete [] c;
In the next Hw, we'll make the bag expandable, so it can upsize as needed to hold more items.
First big change:
ItemType items[DEFAULT_CAPACITY];
becomes
ItemType* items;
So items becomes a pointer to an array pointer.
Second change:
items = new ItemType[myCapacity];
After this, items is a pointer to an array on the heap.
Your constructor also needs to keep track of the current capacity of the bag.
ArrayBag(int capacity = DEFAULT_CAPACITY);
ArrayBag<ItemType>::ArrayBag(int capacity);
ArrayBag<int>aBag(6);
ArrayBag<int>aBag(); // Default Capacity
Third Change
Destructor
delete [] items;
~ArrayBag(); // Destructor call
Fourth Change
resize(int newCapacity)
Make a new item array bigger than the old one,
Copy all the items from the old items array to the new items array
Delete the old items array
Set items = new items array
Update myCapacity to the new array size.
Copy Constructor
You will write a new constructor that initializes a Bag as a copy of another bag.
ArrayBag(const ArrayBag& anotherBag); // copy constructor
// Update itemCount to be anotherBag's itemCount
itemCount = anotherBag.getCurrentSize();
myCapacity = anotherBag.getCapacity();
items = new ItemType[myCapacity];
// loop to copy each item from itmes to new_items
for(int l = 0; k < itemCount; ++k)
items[k] = anotherBag.items[k];
ArrayBag<int>frodo;
frodo.add(5); frodo.add(-2);
ArrayBag<int> bobo = frodo;
Shallow Copy
The same exact shared type/object within memory.
The this pointer
Every object you make knows where it's stored in memory. That address is called this.
We can dereference the this pointer of an object(*this) to get the object itself back
We can also use the this pointer itself to figure out weird vases where our code will be wacky.
For memory, they must be the sam object! We do this when checking for self assignment.
Sixth Change
Operator =
Add an assignment operator to assign one Bag to another.
ArrayBag& operator = (const ArrayBag& anotherBag);
// Assignment Operator
Check if we're self assigning using the address at this; if we are, return *this;
If we're not self assigning, delete our existing items array
Set our myCapacity and itemCount
Then make a new items array with the capacity of anotherBag and copy the items from anotherBag
Then return *this
Underwear test
if(&anotherBag == this)
return *this;
2-7-14
What functions will only have a little change?
getCapacity()
isFull()
add()
Every object you make knows where it's stored in memory. That address is called this.
We can dereference the this pointer of an object (*this) to get the object itself back.
We can also use this pointer itself to figure out weird cases where our code will be wacky. For instance, if 2 objects occupy the same address in memory,
they must be the same exact object. We do this when checking for self assignment.
ArrayBag<string> aBag;
aBag.add("");
ArrayBag<string> fruitBag = aBag;
Array<ItemType>::ArrayBag(const ArrayBag<ItemType>& anotherBag)
{
itemCount = anotherBag.itemCount;
}
anotherBag.itemCount = itemCount; // Bad.
Overwriting an already created bag containing contents will overwrite the bag, recreating it into a copy of the bag's new reassignment with =
bBag = aBag
ArrayBag<ItemType>& ArrayBag<ItemType>::operator=(const ArrayBag<ItemType>& anotherBag)
aBag would be anotherBag in this case.
At the end of the code, suppose that bBag gets automatically destroyed by the destructor, and its items array is released back into the wild memory.
Then aBag gets destroyed. What happens? A seg fault, due to it destroying bBag, then tries to destroy aBag, which is bBag.
2/12/14
First midtem monday 2-2:50
Open book/note
No electronics
Review sheet posted
Bring questions to class Friday.
We defined you class in C++ in 3 parts:
BagInterface.h
ArrayBag.h
ArrayBag.cxx
none of these compiled without the test code
ArrayBagTester.cxx
template<class ItemType>
class BagInterface{ ... }
Defines one bag ancestor class, BagInterface, with a set of empty public methods, like
virtual bool add(const ItemType& newEntry) = 0;
Think of these methods as the core set of functions a user expects from any sort of Bag
In
Remember the BagInterface class name
ArrayBag is defined as decendant of the BagInterface here, after the colon:
template<class ItemType>
class ArrayBag: public BagInterface<ItemType>
The public keyword here means anthing defined as public is also public in ArrayBag (and private is private in ArrayBag)
With those virtual functions, if ArrayBag.cxx doesn't implement them, the compiler complains.
In C++, it's conventional to make a split in a class definition, for 2 reasons:
It's a clumsy way to seperate the interface for the function (what it does) from its implementation (how it does that).
Clumsy because the class member variables are exposed in the header, as are private functions; too much information for an inteface.
It allows any other files that use this class to compile with implicit trust that this class and its methods exist (the implementation code is finally included later in
a final compliation step called linking.)
How did ArrayBagTester.cxx get everything to compile?
ArrayBagTester calls all files together within the compiler, which then correlate into a program.
Macro Guards
ArrayBag.h and BagInterface.h contain macro guards,
#ifndef _ARRAY_BAG
#define _ARRAY_BAG
#endif
Why? it's perferctly likely tht 2 files in a project might #include the same header file (and this might well be needed for them to compile in c++).
But the compiler freaks out if it sees a function or class being defined twice! (it doesn't know which one you mean it to use.)
This first time the compiler sees ArrayBag.h, it checks if it has a variable called Array_Bag defined. If it's needs/seen ArrayBag.h before in the compilation, this variable
is not defined, so #ifndef _ARRAY_BAG (which means if _ARRYA_BAG is not defined) return true. This lets the code define _ARRAY_BAG for the first time, and
read in the header file.
The #endif marks the end of the compiler's #ifndef.
2/14/14
Abstract Class
ex: BagInterface.h
Has virtual functions, but has implementations along with the virtual functions
Virtual Template Class
ex: An extension of an abstract. Can be reformed into children classes
#include <iostream>
using std;
class Animal {
public virtual eat();
public virtual kill();
};
class Human : Animal {
public void think()
{
cout << "LOL" << end; // Now an abstract class
}
};
class Male : Human { // Human extends animal class, male extends human.
public virtual pee_standing_up();
void think() // Overload the function
{
cout << "ROFL" << endl;
}
};
int main()
{
Male m = new Male();
m.think();
Human h = new Human();
h.think();
Animal * a;
a = new Male();
a.think();
}
Polymorphism - Changes parent class into child class
A, goes from animal to male human.
child classes cannot become parent classes.
Class Ball{
int x, y;
virtual void bounce();
void move(){
x += 1; // This function turns class into an abstract class, since it implements individuality.
y += 1;
}
virtual void roll();
Ball()
{
x = 1
y = 1;
}
};
class Football : Ball
{
// IMPLEMENT
void bounce()
{
y += 1;
}
void roll()
{
x += 1;
}
}
int main()
{
Football f = new FootBall();
Ball * b = new FootBall(); // Same behavior
// Ball * a = new Ball(); // Not all implementation are complete, so this will output an confliction error
}
Constructors are inherited. They gain all method inheritence from their class parent.
ex: Ball class, Football gains Ball constructor.
If football has a unique constructor, that is/can be called
Classes can have multiple parents, but it is unethical programming and breaks the structure of programming.
Child functions take precedence.
One-to-one relationships
The ability of one class to use another class.
class Male :: Human
{
public void pee_standing_up();
void think()
{
cout << "ROFL" << endl;
}
Ball * b; // 1-to-1
}
int main()
{
Male m = new Male();
m.think();
m.b = new FootBall()
m.b.roll();
}
1-19-14
How to compute factorial of a positive integer n?
Loop
unsigned in factorial_1(unsigned int n)
{
unsigned int answer = 1;
unsigned int counter = n;
while (counter > 0)
answer *= counter--;
return answer;
}
Recursion
unsigned int factorial_2(unsigned int n)
{
if(n < 2)
return 1;
else
return n * factorial_2(n-1);
}
Recursive functions call themselves
Problem has to get smaller in each recursive call.
Recursive factorial is not so high preformance
Recurive calls cost time
recursive functions with local vars cost lots of space
But other recursive methods are very useful.
Binary search of sorted array
Solution to Towers of Hanoi problem
Quicksort/Heapsort/mergesort to soret arrays
Processing fractals: Koch snowflake, sierpinski triangle
Searching an array for an item
How do we tell if an unsorted array of n items contains a particular item?
When can we stop early? (Like ArrayBag's contains)
When would we have to look at all the items
If there are n items, this takes 0(n) times
Would this become faster if the array were sorted smallest to largest?
When can we stop early?
When would we have to look at all items?
If there are n items, this takes 0(n) time
Can we do better?
2-21-14
Longest Common Subsequence
If we have 2 strings, how similar are they?
What if we answer by counting all the letters?
Is "man bits dog" equal to "dog bites man"?
What if we take order into account?
BANANA vs. NANA
This algorithm is used to compute genetic similarity (BLAST)
This is a problem for a 2D array!
- - B A N A N A
- 0 0 0 0 0 0 0
N 0 ? ? ? ? ? ?
A 0 ? ? ? ? ? ?
N 0 ? ? ? ? ? ?
A 0 ? ? ? ? ? ?
Note: Array has one extra row and column, filled with 0s.
string a = "BANANA";
string b = "NANA";
int** lcs_array = new char*[length(b) + 1];
for(int k = 0; k < length(b) + 1; k++)
lcs_array[k] = new char[length(a) + 1];
Now we fill in the table according to this rule:
If there's a cell in the array at row i and colume k, and the letters of string b[i-1], column j;
the number of row i, colume [j-1]; or 1 + number in row(i-1), column (j-1)
- - B A N A N A
- 0 0 0 0 0 0 0
N 0 0 0 1 1 1 1
A 0 0 1 1 2 2 2
N 0 0 1 2 2 3 3
A 0 0 1 2 3 3 4
2-24-14
HackYourApp: Hackathon
Read Chapter 4, recursion; focus on factorial and binary search sections for now
- - B A N A N A
- 0 0 0 0 0 0 0
N 0 0 0 1 1 1 1
A 0 0 1 1 2 2 2
N 0 0 1 2 2 3 3
A 0 0 1 2 3 3 4
Backtraking to get the match is harder:
B A N A N A
- - N A N A
string a = "BANANA";
string b = "NANA";
int** lcs_array = new char*[length(b) + 1];
for(int k = 0; k < length(b) + 1; k++)
lcs_array[k] = new char[length(a) + 1];
for(int k = 0; k < length(b) + 1; ++k)
delete [] lcs_array[k];
delete [] lcs_array;
- - B O N O B O
- 0 0 0 0 0 0 0
B 0 1 1 1 1 1 1
O 0 1 2 2 2 2 2
B 0 1 2 2 2 3 3
O 0 1 2 2 3 3 4
Backtracing the match is harder (multiple matches can happen)
B O N O B O
B - - O B O
OR
B O N O B O
B O - - B O
Longest common subsequence
Real sequence data is hundreds to millions of letters long
These 2d tables can get huge
What if we has to aling 3 strings?
Exam ANSWERS
1) Pointers! Track this code and tell me what it prints for a, b , and c in the the last line.
63 63 63
2) if (isEmpty)
return false;
biggestitem = items[0]
for(int k = 0; k < itemCount; k++)
if(items[k] > biggestItem)
biggestItem = items[k];
return true;
3) ArrayBag<ItemType> destructThis = *this;
ArrayBag<ItemType> destructAnotherBag = anotherBag;
if(destructAnotherBag.isEmpty() && destructThis.isEmpty())
return true;
if(destructAnotherBag != destructThis)
return false;
while (destructAnotherBag.isEmpty() == false && destructThis.isEmpty() == false)
{
ItemType biggestItem1, biggestItem2;
destructThis.biggest(biggestItem1);
destructAnotherBag.biggest(biggestItem2);
if(biggestItem1 != biggestItem2)
return false
destructThis.remove(biggestItem1);
destructAnotherBag.remove(biggestItem2);
}
4)
5) a. Larry unchanged
b. Eddie, larry unchanged fred change
c. Ted can change, eddit can, larry can't
6)
2-26-14
Read chapter 4
Writeups of the seminars, 6 double spaced pages, by email, plus a couple of references to journals or magazines, and at least half of this paper should talk about your
reaction to the work. Tell me something interesting that you learned.
BigNum numbers
We store these digits backwards, which is really handly later. Don't Store them in forwards order (it's too much work for us to debug)
Watch the odd behavior of unsigned ints (and don't even think of changing these to regular ints; that's not allowed)
BigNum a;
BigNum b = 786;
BigNum c = b;
BigNum d = (string) "928787";
c = a;
b = b;
786 % 10 = 6
786 / 10 = 78
a == b return (!(a == b))
a < b return((a<b)||(a==b))
3-3-14
HW3 Part 1, due 3/8, Part 2, 3/17
Constructor
Destructor
Assignment operators
Why do we need a new class for bigger numbers?
Limitations on ints, on 64 bit ubuntu vm, ints can represent a limited amount of positive and negative numbers. You can determine the limits on your