1 / 31

Linked Lists

Linked Lists. Chapter 10. Linked Lists. What? A Structured data object ( struct ) which relies on pointers between elements Why? Alternative to Sorting Ordering on Multiple keys Relatively easy maintenance Dynamic Memory Allocation. How? Addition of pointer field: .

Download Presentation

Linked Lists

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Linked Lists Chapter 10

  2. Linked Lists • What? • A Structured data object (struct) which relies on pointers between elements • Why? • Alternative to Sorting • Ordering on Multiple keys • Relatively easy maintenance • Dynamic Memory Allocation • How? • Addition of pointer field: struct namelist { char name[30]; struct namelist * next; }; int main() { struct namelist names[4], *head; . . .

  3. Consider the following section of C code: struct custs { char ssn[10]; char name[14]; float balance; struct custs *next; }; int main () { struct custs customer[5] = {{“123456789”,”Chaucer, G.”,342.45,NULL}, {“234567890”,”Milton, J.”,0.00,}, {“345678901”,”Browning, R.”,-51.25,}, {“456789012”,”Eliot, T.S.”,7522.00,}, {“567890123”,”Shelley, P.”,32.44.}}, * first; Where the data type struct custs requires: 10 + 14 + 4 + 4 = 32 Bytes of contiguous storage The variable array customer requires: 32 * 5 = 160 Bytes of contiguous storage & pointer first requires 4 Bytes of contiguous storage

  4. 9335 9213 9216 9212 9200 9201 9351 9202 9203 9350 9205 9349 9207 9348 9206 9347 9346 9211 9210 9208 9209 9218 9329 9219 9204 9220 9336 9215 9344 9337 9217 9343 9342 9341 9340 9339 9338 9214 9328 9223 9330 9331 9222 9332 9333 9221 9334 9345 ‘h’ ‘4’ ‘5’ ‘6’ ‘C’ ‘9’ ‘r’ ‘\0’ ‘3’ ‘7’ ‘2’ ‘6’ ‘8’ ‘\0’ ‘,’ ‘2’ ‘1’ ‘0’ ‘9’ ‘7’ ‘5’ ‘1’ ‘a’ --- ‘c’ --- ‘l’ --- ‘G’ ‘y’ ‘.’ ‘h’ ‘ ’ ‘,’ --- ‘P’ ‘S’ ‘\0’ ‘.’ ‘l’ ‘\0’ ‘e’ ‘8’ ‘3’ ‘e’ ‘e’ ‘u’ 0 ------- 342.45 32.44 ------- 9224 9368 9352 9356 9371 9225 9226 9228 9229 9230 9231 9353 9370 9227 9357 9369 9359 9355 9358 9354 IF the base address of the array customer (== customer[0]) was 9200, then the relevant portion of RAM would appear as: Continuing through And * first might be found at

  5. 9200 - 9209 9296 - 9305 9232 - 9241 9264 - 9273 9328 - 9337 9338 - 9351 9210 - 9223 9274 - 9287 9242 - 9255 9306 - 9319 9288 - 9291 9320 - 9323 9352 - 9355 9256 - 9259 9224 - 9227 9260 - 9263 9324 - 9327 9292 - 9295 9356 - 9359 9228 - 9231 “234567890” “456789012” “123456789” “567890123” “345678901” “Chaucer, G.” “Shelley, P.” “Browning R.” “Eliot, T.S.” “Milton, J.” 0.00 -51.25 32.44 342.45 7522.00 --- --- --- 0 --- How is any of this helpful ??? Notice that the array/table (customer) would appear as: Offset\Field: ssn name balance * next 0 1 2 3 4 Notice that the list is NOT in any order (other than by ssn) What if we wished to sort by, say, name. Could we do it without sorting ??

  6. 9210 - 9223 “Chaucer, G.” 9264 - 9273 9200 - 9209 9328 - 9337 9232 - 9241 9296 - 9305 9338 - 9351 9274 - 9287 9306 - 9319 9242 - 9255 9352 - 9355 9224 - 9227 9256 - 9259 9288 - 9291 9320 - 9323 9324 - 9327 9292 - 9295 9356 - 9359 9260 - 9263 9228 - 9231 “567890123” “345678901” “234567890” “456789012” “123456789” “Browning R.” “Shelley, P.” “Milton, J.” “Eliot, T.S.” 32.44 342.45 7522.00 0.00 -51.25 --- --- 0 --- --- 9264 9368 9369 9371 9370 We Need to set up the linkages. First, identify the initial name: Then store the Base address of the record in location first

  7. 9210 - 9223 “Chaucer, G.” 9296 - 9305 9264 - 9273 9200 - 9209 9328 - 9337 9232 - 9241 9338 - 9351 9242 - 9255 9274 - 9287 9306 - 9319 9224 - 9227 9288 - 9291 9256 - 9259 9352 - 9355 9320 - 9323 9324 - 9327 9260 - 9263 9228 - 9231 9292 - 9295 9292 - 9295 9356 - 9359 “345678901” “567890123” “456789012” “234567890” “123456789” “Eliot, T.S.” “Shelley, P.” “Browning R.” “Milton, J.” 32.44 342.45 -51.25 7522.00 0.00 --- --- --- 0 9200 --- Next, identify the next name on the list: Then have the previous record point to it by storing the new record’s address in field next

  8. 9210 - 9223 “Chaucer, G.” 9328 - 9337 9296 - 9305 9200 - 9209 9264 - 9273 9232 - 9241 9306 - 9319 9338 - 9351 9242 - 9255 9274 - 9287 9320 - 9323 9288 - 9291 9224 - 9227 9352 - 9355 9256 - 9259 9260 - 9263 9260 - 9263 9292 - 9295 9228 - 9231 9228 - 9231 9324 - 9327 9324 - 9327 9356 - 9359 9356 - 9359 “567890123” “345678901” “234567890” “123456789” “456789012” “Browning R.” “Eliot, T.S.” “Milton, J.” “Shelley, P.” -51.25 32.44 7522.00 0.00 342.45 9296 9232 9328 NULL --- --- 0 9200 --- Continue until each record points to the next record: AND set the last record’s next field point to NULL

  9. How do we set up the list? • Add first record (first = customer, customer[0].next = NULL) • For the remaining records: • 1. Starting with 1st record, compare the name with every other name • 2. If the new name is greater than the list name: • A. If end of list: • a. have old record point to new • b. set new record pointer to NULL • Else if the new name is smaller: • A. If first record: • a. set new record next pointer to old record • b. set first pointer to new record • B. Otherwise: • a. have previous record point to new record • b. have new record point to record being compared • 3. Get next record (if any) and go to step 1.

  10. 9232 - 9241 9200 - 9209 9242 - 9255 9210 - 9223 9256 - 9259 9224 - 9227 9228 - 9231 9260 - 9263 “234567890” “123456789” “Chaucer, G.” “Milton, J.” 0.00 342.45 NULL --- 9200 9368 9369 9371 9370 Following the above procedure: Add first record (first = customer], customer[0].next = NULL) Yes Compare the name with the next name on the list: The record should be placed after the first record: • Is the first record the last record?

  11. 9200 - 9209 9232 - 9241 9210 - 9223 9242 - 9255 9224 - 9227 9256 - 9259 9260 - 9263 9228 - 9231 “234567890” “123456789” “Chaucer, G.” “Milton, J.” 342.45 0.00 9232 NULL Have the old record point to the new record by setting in the address of the new record into the old record’s next field: Set the new record’s next field point to NULL Now repeat the procedure, starting with the first record:

  12. 9200 - 9209 9264 - 9273 9210 - 9223 9274 - 9287 9224 - 9227 9288 - 9291 9228 - 9231 9292 - 9295 “123456789” “345678901” “Chaucer, G.” “Browning R.” -51.25 342.45 9232 --- 9200 9368 9370 9371 9369 Compare the name with the new name: The new record should be placed Before the record: • Is the record the First record? Yes

  13. 9200 - 9209 9296 - 9305 9264 - 9273 9210 - 9223 9274 - 9287 9306 - 9319 9320 - 9323 9224 - 9227 9288 - 9291 9228 - 9231 9324 - 9327 9292 - 9295 “456789012” “345678901” “123456789” “Eliot, T.S.” “Chaucer, G.” “Browning R.” 342.45 7522.00 -51.25 --- 9232 9200 9264 9368 9370 9371 9369 Store the address of the new first record at address first: And have the new first record point to the old one: Repeat the previous process starting with the new first record: The new record FOLLOWS the first record: • Is the first record the LAST record in the list? No

  14. 9296 - 9305 9264 - 9273 9232 - 9241 9200 - 9209 9242 - 9255 9274 - 9287 9210 - 9223 9306 - 9319 9320 - 9323 9288 - 9291 9224 - 9227 9256 - 9259 9228 - 9231 9292 - 9295 9260 - 9263 9324 - 9327 “345678901” “123456789” “456789012” “234567890” “Chaucer, G.” “Eliot, T.S.” “Browning R.” “Milton, J.” 342.45 0.00 7522.00 -51.25 NULL --- 9232 9200 Continue by comparing with the next item on the existing list: The new record FOLLOWS the existing record: • Is the existing record the LAST record in the list? No Get the next item on the list

  15. 9232 - 9241 9296 - 9305 9242 - 9255 9306 - 9319 9256 - 9259 9320 - 9323 9324 - 9327 9260 - 9263 “234567890” “456789012” “Eliot, T.S.” “Milton, J.” 7522.00 0.00 NULL --- 9264 9368 9370 9371 9369 Compare the two items: The new record GOES BEFORE the existing record: • Is the existing record the FIRST record in the list? No Insert the new item in the list by: • Having the previous record point to the new record • Having the new record point to the existing record

  16. first 9296 - 9305 9328 - 9337 9264 - 9273 9232 - 9241 9200 - 9209 9306 - 9319 9242 - 9255 9338 - 9351 9210 - 9223 9274 - 9287 9256 - 9259 9352 - 9355 9288 - 9291 9224 - 9227 9320 - 9323 9292 - 9295 9324 - 9327 9260 - 9263 9356 - 9359 9228 - 9231 “234567890” “567890123” “123456789” “345678901” “456789012” “Browning R.” “Shelley, P.” “Milton, J.” “Eliot, T.S.” “Chaucer, G.” 32.44 7522.00 342.45 0.00 -51.25 9296 NULL 9232 --- 9200 9264 9368 9369 9370 9371 So far, our database would appear as: Offset\Field: ssn name balance * next 0 1 2 3 4 With only one record NOT set into the list:

  17. first 9328 - 9337 9264 - 9273 9274 - 9287 9338 - 9351 9288 - 9291 9352 - 9355 9356 - 9359 9292 - 9295 “345678901” “567890123” “Browning R.” “Shelley, P.” -51.25 32.44 --- 9200 9264 9368 9370 9371 9369 Add The final record by repeating all of the steps: Compare with The new record FOLLOWS the existing record: • Is the existing record the LAST record in the list? Get the next item on the list No

  18. 9200 - 9209 9328 - 9337 9264 - 9273 9296 - 9305 9210 - 9223 9338 - 9351 9306 - 9319 9274 - 9287 9288 - 9291 9320 - 9323 9352 - 9355 9224 - 9227 9228 - 9231 9292 - 9295 9356 - 9359 9324 - 9327 “345678901” “456789012” “123456789” “567890123” “Shelley, P.” “Eliot, T.S.” “Chaucer, G.” “Browning R.” 7522.00 -51.25 342.45 32.44 9232 9200 --- 9232 Continue: The new record FOLLOWS the existing record: • Is the existing record the LAST record in the list? No Get the next item on the list

  19. 9296 - 9305 9232 - 9241 9328 - 9337 9306 - 9319 9242 - 9255 9338 - 9351 9320 - 9323 9352 - 9355 9256 - 9259 9324 - 9327 9356 - 9359 9260 - 9263 “456789012” “234567890” “567890123” “Milton, J.” “Eliot, T.S.” “Shelley, P.” 32.44 0.00 7522.00 NULL --- 9232 Continue Comparisons: The new record FOLLOWS the existing record: • Is the existing record the LAST record in the list? Get the next item on the list No

  20. 9232 - 9241 9232 - 9241 9328 - 9337 9328 - 9337 9242 - 9255 9338 - 9351 9338 - 9351 9242 - 9255 9256 - 9259 9352 - 9355 9352 - 9355 9256 - 9259 9260 - 9263 9356 - 9359 9260 - 9263 9356 - 9359 “234567890” “234567890” “567890123” “567890123” “Milton, J.” “Shelley, P.” “Shelley, P.” “Milton, J.” 32.44 0.00 32.44 0.00 --- NULL 9328 NULL Continue Comparisons: The new record FOLLOWS the existing record: • Is the existing record the LAST record in the list? Set the item into the list YES The old last item points to the new item: And the new item points to NULL:

  21. #include <string.h> // for strcmp struct custs { char ssn[10], name[30]; // stucture template float balance; struct custs *next; }; int main () { struct custs customer[5] = // initialize array {{“123456789”,”Chaucer, G.”,342.45,NULL}, {“234567890”,”Milton, J.”,0.00,}, {“345678901”,”Browning, R.”,-51.25,}, {“456789012”,”Eliot, T.S.”,7522.00,}, {“567890123”,”Shelley, P.”,32.44,}}; struct custs *first = customer, *present, *previous; int recno; for (recno = 1; recno < 5; recno++) { present = first; // start with 1st record on list // Is the new record larger AND are there additional records? while ((strcmp(customer[recno].name,present->name)>0) && (present->next != NULL)) { previous = present; // old record now previous present = present->next; } // Then get the next record // Why are we out of the loop? Was the new < old record? if (strcmp(customer[recno].name,present->name) < 0) { if (present == first) first = &customer[recno]; // reset first pointer else previous->next = &customer[recno]; // prev -> new customer[recno].next = present; } // new -> old else // new > old { if (present->next == NULL) customer[recno].next = NULL; // new -> NULL else customer[recno].next = present->next; // new-> old present->next = &customer[recno]; } // old -> new } // the list is linked }

  22. first 9296 - 9305 9200 - 9209 9264 - 9273 9306 - 9319 9210 - 9223 9274 - 9287 9288 - 9291 9320 - 9323 9224 - 9227 9228 - 9231 9324 - 9327 9292 - 9295 “123456789” “456789012” “345678901” “Chaucer, G.” “Browning R.” “Eliot, T.S.” -51.25 342.45 7522.00 9296 9232 9200 9264 9368 9371 9370 9369 How would we search for an item on the list? We need to perform a sequential search. Suppose we were looking for: “Eliot, T.S.”(which is the 3rd element (alphabetically) and 4th element (physically) on the list). Starting at the top: Search Element? No: Get Next Search Element? No: Get Next Search Element? YES: Stop

  23. The C Code Necessary ?? Building on the previous code, consider the following additional code: char temp[50]; // Temporary Storage printf(“Enter Name to search for: ); // Prompt User gets(temp); // Get Input present = first; // point to the 1st record while ((present != NULL) && (strcmp(temp,present->name) < 0)) present = present->next; // Get next record if ((present == NULL) || (strcmp(temp, present->name) >0)) printf(“\nThe Name is not on the list”); // Element not in list else // Element in list printf(“\nThe name %s is on the list”, present->name); Notice that there is one advantage to sequentially searching an ordered list: We Do NOT Have to search until the end IF the item is NOT on the list

  24. There are other advantages to linked lists: Additional Advantage 1: Ordering on multiple keys: • In addition to listing items by name, we could also list items by, for example, balance, WITHOUT physically sorting. • Consider the following change in our structure template and initial declarations: struct custs { char ssn[10]; char name[14]; float balance; struct custs *next_name, *next_balance; }; int main () { struct custs customer[5] = {{ …}}, *first_name = cutomer->name, *first_balance = customer->balance; . . . . . . . . . . . . . . . } Our Database might appear as:

  25. *first_balance *first_name *next_ name *next _balance 9200 - 9209 9210 - 9223 9224 - 9227 9228 - 9231 9232 - 9235 9372 - 9375 9264 - 9267 9368 - 9371 9376 - 9379 9260 - 9263 9336 - 9339 9332 - 9335 9340 - 9343 9304 - 9307 9300 - 9303 9296 - 9299 9268 - 9271 ssn name balance “123456789” “Chaucer, G.” -51.25 9344 NULL 9308 9344 9200 9308 0.00 7522.00 9236 NULL 9200 32.44 342.45 9236 9264 9264 9272-9281 9308-9317 9236 - 9245 9344-9353 9246 - 9259 “345678901” “Milton, J.” “567890123” “234567890” “456789012” 9368 9368 9370 9369 9371 9370 9371 9369 9318 - 9331 9282 - 9295 9354 - 9367 Shelley, P.” “Eliot, T.S.” “Browning R.” Order by name Order by balance

  26. 9204 - 9213 9214 - 9227 9340 - 9343 9308 - 9311 9336 - 9339 9268- 9271 9264 - 9267 9344 - 9347 9236- 9239 9304 - 9307 9232 - 9235 9228 - 9231 9200 - 9203 9272 - 9275 9300 - 9303 9372 - 9375 9376 - 9379 “123456789” “Chaucer, G.” 9236 7522.00 9200 9344 9236 0.00 9308 9200 -51.25 9272 342.45 NULL 9308 NULL 32.44 9312-9321 9240 - 9249 9250 - 9263 9276-9285 9348-9357 “456789012” “234567890” “Milton, J.” “345678901” “567890123” 9322 - 9335 9358 - 9371 9286 - 9299 “Eliot, T.S.” Shelley, P.” “Browning R.” Why?? We can also have doubly-linked lists. To allow us to search from either end of the list. Consider the structured object: struct custs { struct custs * previous; char ssn[10], name[14]; float balance; struct custs *next; }; Our database might appear as:

  27. 9204 - 9213 9214 - 9227 9308 - 9311 9336 - 9339 9340 - 9343 9268- 9271 9264 - 9267 9344 - 9347 9236- 9239 9304 - 9307 9272 - 9275 9300 - 9303 9228 - 9231 9232 - 9235 9200 - 9203 9376 - 9379 9372 - 9375 “123456789” “Chaucer, G.” 7522.00 9236 9200 9344 9236 9308 0.00 9200 NULL -51.25 342.45 9308 9272 NULL 32.44 9312-9321 9240 - 9249 9250 - 9263 9276-9285 9348-9357 “456789012” “234567890” “Milton, J.” “345678901” “567890123” 9322 - 9335 9358 - 9371 9286 - 9299 “Browning R.” “Eliot, T.S.” Shelley, P.” The links would appear as:

  28. 9200 - 9209 9210 - 9223 9436- 9439 9432- 9435 9420- 9423 9424- 9427 9428- 9431 9224 - 9227 9270 - 9273 9242 - 9245 9298 - 9301 9326 - 9329 “123456789” “Chaucer, G.” 9274 9228 9200 9246 9302 0.00 32.44 342.45 -51.25 7522.00 9246-9255 9274-9283 9238- 9241 9228 - 9237 9302-9311 “234567890” “345678901” “Milton, J.” “456789012” “567890123” 9312 - 9325 9284- 9297 9256 - 9269 “Eliot, T.S.” “Browning R.” Shelley, P.” Are there additional Searching techniques on linked lists? We could set up an array of pointers: struct custs { char ssn[10], name[14]; float balance; }; int main() { struct custs customer[5] = {{…}}, *order[5];

  29. 5150 5000 9th 8th 8th 1st 5150 5125 5025 5175 2nd 4th 5200 5050 12th 7th 4th 12th 5050 5175 5225 5075 5th 6th 5100 5250 11th 10th 5275 5125 3rd 1st We could also set up leveled lists:

  30. Comparison of linkage Types Single Linked List: AdvantageDisadvantage Ease of creation Sequential Search only Ease of update Search in One direction (only) 2-extra bytes Doubly Linked List: AdvantageDisadvantage Search both directions 4-extra bytes/record Still easy create/update Still Sequential Search Array of Pointers: AdvantageDisadvantage Binary Search More difficult to create Search both directions and update (longer lists) (Only) 2-extra bytes/rec NOTE: All of these linkages require that we know IN ADVANCE how many records there are

More Related