-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
323 lines (290 loc) · 11.1 KB
/
Copy pathmain.cpp
File metadata and controls
323 lines (290 loc) · 11.1 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
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <list>
//structure to define Car categories given data set
struct Car {
//all in order of data set
//def height, length, and width
int height, length, width;
//def driveline and engine type
std::string driveline, engineType;
//def for if car hybrid or not
bool hybrid;
//def for number of gears
int numOfGears;
//def for type of transmission
std::string transmission;
//def fuel efficiency for city
int cityMpg;
//def fuel type
std::string fuelType;
//def fuel efficiency for highway
int highwayMpg;
//def car classification (compact, sedan, SUV), unique ID, make (manufacturer), and model year
std::string classification, id, make, modelYear;
//def car model year(dif than string rep), horsepower, and torque
int year, horsepower, torque;
};
//Def size of the hash tables
//for over 100,000 data points
const int TABLE_SIZE = 142889;
//for Linear Probing (hash table)
//struct to def key-value pair to be stored in the linear hash table
struct LinearEntry {
//def key (for hashing and retrieval)
std::string key;
Car value;
//for if entry occupied
bool occupied = false;
};
//static array of LinearEntry elements
//of hash table
LinearEntry linearHashTable[TABLE_SIZE];
//similar but for Separate Chaining (hash table)
//struct def ChainEntry (no occupied check needed)
struct ChainEntry {
//def key (for hashing and retrieval)
std::string key;
Car value;
//no occupied check, will auto do w/ empty nodes (linked lists)
};
//static array of ChainEntry elements
//of hash table
std::list<ChainEntry> chainHashTable[TABLE_SIZE];
//function converts a string key into an index in the hash table
int hashFunction(const std::string& key) {
int hash = 0;
//will iterates through each character of the string key
for (char c : key) {
//update hash table based on prev val + ASCII val of current char
hash = (hash * 31 + c) % TABLE_SIZE;
}
return hash;
}
//for linear probing
//Insert function
void linearInsert(const std::string& key, const Car& value) {
//to generate index for this key
int index = hashFunction(key);
//check if the spot is occupied will linearly probe to the next index
while (linearHashTable[index].occupied) {
index = (index + 1) % TABLE_SIZE;
}
//to store the key-value pair in the hash table
linearHashTable[index].key = key;
linearHashTable[index].value = value;
//set the occupied flag to true
linearHashTable[index].occupied = true;
}
//for linear probing
//Search function
Car* linearSearch(const std::string& key) {
//to generate index for this key
int index = hashFunction(key);
//temp var to ref starting index
int startIndex = index;
//do-while loop for checking each spot in the hash table
//start from the hashed index
do {
//check if the spot's key matches the search key
if (linearHashTable[index].key == key) {
//return a pointer to the value
return &linearHashTable[index].value;
}
//if not, linearly probe to the next index
index = (index + 1) % TABLE_SIZE;
//continue while spot is occupied given the search not restarted to start index
} while (linearHashTable[index].occupied && index != startIndex);
//if key not found
return nullptr;
}
//for Separate Chaining
//function to insert a key-value pair into the separate chaining hash table
void chainInsert(const std::string& key, const Car& value) {
//hash the key to get an index
int index = hashFunction(key);
//temp: new ChainEntry to hold the key-value pair
ChainEntry entry;
entry.key = key;
entry.value = value;
//add the entry to the end of the chain
chainHashTable[index].push_back(entry);
}
//function to search for a key in the separate chaining hash table
Car* chainSearch(const std::string& key) {
//hash the key to get an index
int index = hashFunction(key);
//iterate through the chain at computed index
for (auto& entry : chainHashTable[index]) {
//If the current entry's key = the search key
if (entry.key == key) {
//return a pointer to value
return &entry.value;
}
}
//otherwise if key not found
return nullptr;
}
//for both linear probing, separate chaining
//function to read data from a CSV file and insert to specfic hash table
//to read file
std::vector<Car> readCarsFromCSV(const std::string &filename, bool useLinearProbing) {
//open file
std::ifstream file(filename);
//vector to store the cars data
std::vector<Car> cars;
std::string line, token;
//test file not opening
if (!file.is_open()) {
std::cerr << "Could not open the file: " << filename << std::endl;
return cars;
}
//to ignore the header row
//cause this is just the titles of the categoreis of data
std::getline(file, line);
//process each line in the file
while (std::getline(file, line)) {
//use a stringstream to split the line into tokens
std::stringstream ss(line);
//temp: new car object
//holds data for this line
Car car;
//Vector to hold tokens
std::vector<std::string> columns;
//to split the line into tokens based on commas (of file, sep data)
while (std::getline(ss, token, ',')) {
//to check if the token is enclosed in double quotes
//so data is read correctly from file
size_t start = token.find_first_of("\"");
size_t end = token.find_last_of("\"");
//if quotes remove them and add the token to the columns vector
if (start != std::string::npos && end != std::string::npos) {
columns.push_back(token.substr(start + 1, end - start - 1));
//otherwise still add the token to the columns vector (no quotes)
} else {
columns.push_back(token);
}
}
//so that all data of car inputed can be outputted
//check if line does not have the correct number of columns (18)
//then skip it
if (columns.size() != 18) {
continue;
}
//to parse the data from the columns into the Car object
//of each of the categorries of the data from the file
try {
car.height = std::stoi(columns[0]);
car.length = std::stoi(columns[1]);
car.width = std::stoi(columns[2]);
car.driveline = columns[3];
car.engineType = columns[4];
car.hybrid = (columns[5] == "True");
car.numOfGears = std::stoi(columns[6]);
car.transmission = columns[7];
car.cityMpg = std::stoi(columns[8]);
car.fuelType = columns[9];
car.highwayMpg = std::stoi(columns[10]);
car.classification = columns[11];
car.id = columns[12];
car.make = columns[13];
car.modelYear = columns[14];
car.year = std::stoi(columns[15]);
car.horsepower = std::stoi(columns[16]);
car.torque = std::stoi(columns[17]);
//Add the Car to the vector of cars
cars.push_back(car);
//to insert the Car into the selected hash table via user
//Linear Probing or Separate Chaining insert methods
if (useLinearProbing) {
linearInsert(car.id, car);
} else {
chainInsert(car.id, car);
}
//check if error from processing a line
} catch (const std::invalid_argument &e) {
//state error occured, skip line
std::cerr << "Error occurred while processing line: " << line << "\nError: " << e.what() << std::endl;
continue;
}
}
return cars;
}
int main() {
//file of refrence.
const std::string filename = "cars.csv";
//vector to hold all cars data from file.
std::vector<Car> cars;
//runs until user inputs terminate.
while (true) {
//user chooses hashing approach (Linear Probing or Separate Chaining)
std::cout << "Choose Hashing Approach:\n";
std::cout << "1. Linear Probing\n";
std::cout << "2. Separate Chaining\n";
std::cout << "Enter choice (1/2) or 'terminate' to quit: ";
//input
std::string choiceStr;
std::getline(std::cin, choiceStr);
//break to end program
if (choiceStr == "terminate") {
break;
}
//of user choice
int choice = std::stoi(choiceStr);
//of which method to use based on user choice
switch (choice) {
//if user chooses Linear Probing
case 1: // User chooses Linear Probing
cars = readCarsFromCSV(filename, true);
break;
//if user chooses Separate Chaining
case 2:
cars = readCarsFromCSV(filename, false);
break;
//if input not 1 or 2
default:
std::cerr << "Invalid choice.\n";
continue;
}
//display user to enter car ID or terminate
std::cout << "\nEnter Identification.ID to search for (or 'terminate' to quit): ";
//store input
std::string testId;
std::getline(std::cin, testId);
//break to end program
if (testId == "terminate") {
break;
}
//to search for car from data based on user's choice of hashing
Car* foundCar = (choice == 1) ? linearSearch(testId) : chainSearch(testId);
//If car is found, print data from all categories (18)
if (foundCar) {
std::cout << "Found in hash map: \n";
std::cout << "Height: " << foundCar->height << "\n";
std::cout << "Length: " << foundCar->length << "\n";
std::cout << "Width: " << foundCar->width << "\n";
std::cout << "Driveline: " << foundCar->driveline << "\n";
std::cout << "Engine Type: " << foundCar->engineType << "\n";
std::cout << "Hybrid: " << (foundCar->hybrid ? "True" : "False") << "\n";
std::cout << "Number of Gears: " << foundCar->numOfGears << "\n";
std::cout << "Transmission: " << foundCar->transmission << "\n";
std::cout << "City MPG: " << foundCar->cityMpg << "\n";
std::cout << "Fuel Type: " << foundCar->fuelType << "\n";
std::cout << "Highway MPG: " << foundCar->highwayMpg << "\n";
std::cout << "Classification: " << foundCar->classification << "\n";
std::cout << "ID: " << foundCar->id << "\n";
std::cout << "Make: " << foundCar->make << "\n";
std::cout << "Model Year: " << foundCar->modelYear << "\n";
std::cout << "Year: " << foundCar->year << "\n";
std::cout << "Horsepower: " << foundCar->horsepower << "\n";
std::cout << "Torque: " << foundCar->torque << "\n";
//otherwise if not found
} else {
std::cout << "Car with ID " << testId << " not found." << std::endl;
}
}
return 0;
}