Advertisement
cd62131

friends list

May 16th, 2019
667
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.80 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. typedef struct plist plist;
  5. typedef struct {
  6.   char *name;
  7.   plist *friends;
  8. } person;
  9. struct plist {
  10.   person *data;
  11.   plist *next;
  12. };
  13. static person *person_alloc(char *name) {
  14.   person *new = calloc(sizeof(*new), 1);
  15.   new->name = strdup(name), new->friends = NULL;
  16.   return new;
  17. }
  18. static void print_person(person *p) {
  19.   printf("Name: %s, friends: { ", p->name);
  20.   for (plist *pl = p->friends; pl; pl = pl->next) {
  21.     printf("%s, ", pl->data->name);
  22.   }
  23.   puts("}");
  24. }
  25. static void plist_add(plist **plp, person *p) {
  26.   plist *new = calloc(sizeof(*new), 1);
  27.   new->data = p, new->next = *plp, *plp = new;
  28. }
  29. static void become_friends(person *p1, person *p2) {
  30.   plist_add(&(p1->friends), p2), plist_add(&(p2->friends), p1);
  31. }
  32. static void print_common_friends(person *p1, person *p2) {
  33.   printf("%s and %s have common friends: { ", p1->name, p2->name);
  34.   for (plist *pl1 = p1->friends; pl1; pl1 = pl1->next) {
  35.     for (plist *pl2 = p2->friends; pl2; pl2 = pl2->next) {
  36.       if (pl1->data == pl2->data) { printf("%s, ", pl1->data->name); }
  37.     }
  38.   }
  39.   puts("}");
  40. }
  41. typedef struct pqueue_data pqueue_data;
  42. struct pqueue_data {
  43.   person *person;
  44.   int hop;
  45.   pqueue_data *next;
  46. };
  47. typedef struct pqueue pqueue;
  48. struct pqueue {
  49.   pqueue_data *head, *tail;
  50. };
  51. static void plist_free(plist *pl) {
  52.   if (!pl) { return; }
  53.   plist_free(pl->next), free(pl);
  54. }
  55. static void person_free(person *p) {
  56.   if (!p) { return; }
  57.   plist_free(p->friends), free(p->name), free(p);
  58. }
  59. static int plist_contains(plist *pl, person *p) {
  60.   if (!pl) { return 0; }
  61.   if (pl->data == p) { return 1; }
  62.   return plist_contains(pl->next, p);
  63. }
  64. static pqueue *pqueue_alloc(void) {
  65.   pqueue *new = calloc(sizeof(*new), 1);
  66.   new->head = new->tail = NULL;
  67.   return new;
  68. }
  69. static pqueue_data *pqueue_data_alloc(person *p, int hop) {
  70.   pqueue_data *new = calloc(sizeof(*new), 1);
  71.   new->person = p, new->hop = hop, new->next = NULL;
  72.   return new;
  73. }
  74. static void pqueue_data_free(pqueue_data *p) {
  75.   if (!p) { return; }
  76.   pqueue_data_free(p->next), free(p);
  77. }
  78. static void pqueue_free(pqueue *q) {
  79.   if (!q) { return; }
  80.   pqueue_data_free(q->head), free(q);
  81. }
  82. static void pqueue_put(pqueue *q, person *p, int n) {
  83.   pqueue_data *new = pqueue_data_alloc(p, n);
  84.   if (!q->head) {
  85.     q->head = q->tail = new;
  86.     return;
  87.   }
  88.   q->tail->next = new, q->tail = new;
  89. }
  90. static int pqueue_get(pqueue *q, person **pp, int *np) {
  91.   if (!q->head) { return 0; }
  92.   *pp = q->head->person, *np = q->head->hop;
  93.   if (q->head == q->tail) {
  94.     pqueue_data_free(q->head), q->head = q->tail = NULL;
  95.   } else {
  96.     pqueue_data *p = q->head;
  97.     q->head = p->next, p->next = NULL, pqueue_data_free(p);
  98.   }
  99.   return 1;
  100. }
  101. static int access_ok1(person *p1, person *p2, plist **visited, pqueue *q,
  102.                       int maxhop) {
  103.   person *p;
  104.   int hop;
  105.   pqueue_put(q, p1, 0);
  106.   while (pqueue_get(q, &p, &hop)) {
  107.     plist_add(visited, p);
  108.     if (maxhop < hop) { return 0; }
  109.     if (plist_contains(p2->friends, p)) { return 1; }
  110.     for (plist *pl = p->friends; pl; pl = pl->next) {
  111.       person *f = pl->data;
  112.       if (!plist_contains(*visited, f)) { pqueue_put(q, f, hop + 1); }
  113.     }
  114.   }
  115.   return 0;
  116. }
  117. static int access_ok(person *p1, person *p2, int maxhop) {
  118.   plist *visited = NULL;
  119.   pqueue *q = pqueue_alloc();
  120.   int result = access_ok1(p1, p2, &visited, q, maxhop);
  121.   pqueue_free(q), plist_free(visited);
  122.   return result;
  123. }
  124. int main(void) {
  125.   person *alice = person_alloc("Alice"), *bob = person_alloc("Bob"),
  126.          *carol = person_alloc("Carol"), *dave = person_alloc("Dave"),
  127.          *ellen = person_alloc("Ellen"), *frank = person_alloc("Frank");
  128.   become_friends(alice, bob), become_friends(alice, carol),
  129.       become_friends(bob, dave), become_friends(carol, dave),
  130.       become_friends(carol, ellen), become_friends(carol, frank),
  131.       become_friends(dave, ellen), become_friends(ellen, frank);
  132.   person *person_array[] = {alice, bob, carol, dave, ellen, frank};
  133.   size_t size = sizeof(person_array) / sizeof(person_array[0]);
  134.   { print_person(alice), print_person(bob), print_person(frank); }
  135.   { print_common_friends(alice, frank); }
  136.   {
  137.     int c = 0;
  138.     for (size_t hop = 0; hop < size; ++hop, c = 0) {
  139.       printf("!%zd hop friend\n", hop);
  140.       for (size_t i = 0; i < size; ++i) {
  141.         for (size_t j = 0; j < size; ++j) {
  142.           if (i == j) { continue; }
  143.           if (access_ok(person_array[i], person_array[j], hop)) {
  144.             printf("  %s --> %s\n", person_array[i]->name,
  145.                    person_array[j]->name);
  146.             ++c;
  147.           }
  148.         }
  149.       }
  150.       if ((int)size * ((int)size - 1) <= c) { break; }
  151.     }
  152.   }
  153.   {
  154.     for (size_t i = 0; i < size; ++i) { person_free(person_array[i]); }
  155.   }
  156. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement