213 lines
3.6 KiB
C
213 lines
3.6 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#define MAX 100
|
|
|
|
typedef struct Node {
|
|
int data, degree;
|
|
struct Node *child, *sibling, *parent;
|
|
} Node;
|
|
|
|
typedef struct list {
|
|
int size;
|
|
Node **arr;
|
|
} list;
|
|
|
|
list *newList() {
|
|
list *new = malloc(sizeof(list));
|
|
new->size = 0;
|
|
new->arr = malloc(sizeof(Node *) * MAX);
|
|
return new;
|
|
}
|
|
|
|
void pushBack(list *l, Node *new) { l->arr[l->size++] = new; }
|
|
|
|
void erase(list *l, int loc) {
|
|
for (int i = loc; i < l->size - 1; i++) {
|
|
l->arr[i] = l->arr[i + 1];
|
|
}
|
|
// remember this:
|
|
l->size--;
|
|
}
|
|
|
|
void swapNode(Node *l, Node *r) {
|
|
Node *tmp = malloc(sizeof(Node));
|
|
*tmp = *l;
|
|
*l = *r;
|
|
*r = *tmp;
|
|
}
|
|
|
|
Node *newNode(int val) {
|
|
Node *new = malloc(sizeof(Node));
|
|
|
|
new->data = val;
|
|
new->degree = 0;
|
|
new->child = new->parent = new->sibling = NULL;
|
|
|
|
return new;
|
|
}
|
|
|
|
list *unionList(list *l1, list *l2) {
|
|
list *l = newList();
|
|
|
|
int i = 0, j = 0;
|
|
|
|
while (i < l1->size && j < l2->size) {
|
|
// push the one with smaller degree first
|
|
if (l1->arr[i]->degree <= l2->arr[j]->degree) {
|
|
pushBack(l, l1->arr[i]);
|
|
i++;
|
|
} else {
|
|
pushBack(l, l2->arr[j]);
|
|
j++;
|
|
}
|
|
}
|
|
|
|
while (i < l1->size) {
|
|
pushBack(l, l1->arr[i]);
|
|
i++;
|
|
}
|
|
|
|
while (j < l2->size) {
|
|
pushBack(l, l2->arr[j]);
|
|
j++;
|
|
}
|
|
return l;
|
|
}
|
|
|
|
Node *merge(Node *l, Node *r) {
|
|
if (l->data > r->data) {
|
|
swapNode(l, r);
|
|
}
|
|
|
|
// sub-node might have a sibling, but head node doesn't have one.
|
|
r->parent = l;
|
|
r->sibling = l->child;
|
|
|
|
l->child = r;
|
|
l->degree++;
|
|
|
|
return l;
|
|
}
|
|
|
|
list *adjust(list *l) {
|
|
if (l->size <= 1) {
|
|
return l;
|
|
}
|
|
|
|
int i = 0, j = 0, k = 0;
|
|
|
|
if (l->size == 2) {
|
|
j = i + 1;
|
|
k = l->size;
|
|
} else {
|
|
j++;
|
|
k = j + 1;
|
|
}
|
|
|
|
// can't use i != size here, since the list will shrink.
|
|
while (i < l->size) {
|
|
// only one element remains, if j > size, then i == size
|
|
if (j == l->size) {
|
|
i++;
|
|
} else if (l->arr[i]->degree < l->arr[j]->degree) {
|
|
i++;
|
|
j++;
|
|
if (k < l->size) {
|
|
k++;
|
|
}
|
|
} else if (k < l->size && l->arr[i]->degree == l->arr[j]->degree &&
|
|
l->arr[i]->degree == l->arr[k]->degree) {
|
|
// at most 3 same degrees, because of binary operations
|
|
i++;
|
|
j++;
|
|
k++;
|
|
} else if (l->arr[i]->degree == l->arr[j]->degree) {
|
|
l->arr[i] = merge(l->arr[i], l->arr[j]);
|
|
erase(l, j);
|
|
// doesn't have to move k
|
|
}
|
|
}
|
|
|
|
return l;
|
|
}
|
|
|
|
list *insertTree(list *l, Node *tree) {
|
|
list *temp = newList();
|
|
|
|
pushBack(temp, tree);
|
|
|
|
temp = unionList(l, temp);
|
|
|
|
return adjust(temp);
|
|
}
|
|
|
|
list *insert(list *l, int key) {
|
|
Node *temp = newNode(key);
|
|
return insertTree(l, temp);
|
|
}
|
|
|
|
void traverseLevel(Node* h, int level) {
|
|
if (h) {
|
|
traverseLevel(h->sibling, level);
|
|
if (level == 1) {
|
|
printf("%d,", h->data);
|
|
} else {
|
|
traverseLevel(h->child, level - 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
void printTree(Node *h) {
|
|
int i = 0;
|
|
for (Node* ptr = h; ptr != NULL; ptr = ptr->child) {
|
|
i++;
|
|
traverseLevel(h, i);
|
|
}
|
|
}
|
|
|
|
void printHeap(list *l, int k) {
|
|
int present = 0;
|
|
for (int i = 0; i < l->size; i++) {
|
|
if (l->arr[i]->degree == k) {
|
|
printTree(l->arr[i]);
|
|
present = 1;
|
|
}
|
|
}
|
|
|
|
if (present == 0) {
|
|
printf("0,");
|
|
}
|
|
}
|
|
|
|
int getDigits(int i) {
|
|
int count = 0;
|
|
while (i) {
|
|
count ++;
|
|
i /= 10;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
int main(void) {
|
|
list *l = newList();
|
|
|
|
char buf[MAX];
|
|
scanf("%s", buf);
|
|
int tmp, offset = 0;
|
|
|
|
while (sscanf(buf + offset, "%d,", &tmp) != EOF) {
|
|
// printf("%d is scanned, offset: %d\n", tmp, offset);
|
|
l = insert(l, tmp);
|
|
offset += getDigits(tmp) + 1;
|
|
}
|
|
|
|
int treeNum;
|
|
|
|
scanf("%d", &treeNum);
|
|
|
|
printHeap(l, treeNum);
|
|
|
|
return 0;
|
|
}
|