jamesjlinden
11/5/2014 - 1:12 AM

deep_copy.c

deep_copy.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct s_node {
	struct s_node *next;
	struct s_node *reference;
};

struct s_node *duplicate_list(struct s_node *list);
struct s_node *create_node();
void delete_list(struct s_node *list);

struct s_node *duplicate_list(struct s_node *list) {
	struct s_node *oldListHead = list;
	struct s_node *listIter = list;
	struct s_node *newListHead = 0;
	struct s_node *newListIter = 0;

	/* Create a new node in the new list for each node 
	 * in the existing list 
	 */
	while (listIter != 0) {
		if (newListIter == 0) {
			newListIter = create_node();
			newListHead = newListIter;
		} else {
			(*newListIter).next = create_node();
			newListIter = (*newListIter).next;
		}

		listIter = (*listIter).next;
	}

	/* Walk the list */
	listIter = oldListHead;
	newListIter = newListHead;

	/* Hook up the node references */
	while (listIter != 0) {
		/* Find the number of jumps necessary for each node reference */
		int nodeHasReference = 0;
		int refNodeDistFromHead = 0;
		if ((*listIter).reference != 0) {
			nodeHasReference = 1;

			/* Start at beginning of old list, find num of jumps
			 * to reference node in old list
			 */
			struct s_node *oldNodeRefIter = oldListHead;
			struct s_node *referenceNode = (*listIter).reference;
			while (oldNodeRefIter != 0 && oldNodeRefIter != referenceNode) {
				++refNodeDistFromHead;
				oldNodeRefIter = (*oldNodeRefIter).next;
			}

			/* Make sure the reference node is actually in the list */
			if (oldNodeRefIter == 0) {
				nodeHasReference = 0;
			}
		}

		/* Attach corresponding node in the new list */
		if (nodeHasReference == 1) {
			struct s_node *refNodeInNewList = newListHead;

			int i = 0;
			for (i = 0; i < refNodeDistFromHead; ++i) {
				refNodeInNewList = (*refNodeInNewList).next;
			}	

			(*newListIter).reference = refNodeInNewList;
		}

		listIter = (*listIter).next;
		newListIter = (*newListIter).next;
	}

	return newListHead;
}

void delete_list(struct s_node *list) {
	while (list != 0) {
		struct s_node *temp = list;
		list = (*list).next;
		free(temp);
	}
}

struct s_node *create_node() {
	struct s_node *newNode = (struct s_node *)malloc(sizeof(struct s_node));
	(*newNode).next = 0;
	(*newNode).reference = 0;

	return newNode;
}

void print_list(struct s_node *list) {
	while (list != 0) {
		printf(" addr: %p", list);
		if ((*list).reference != 0) {
			printf(" references addr: %p", (*list).reference);
		} 
		printf("\n");
		list = (*list).next;
	}	
}

int main() {
	/* Create a linked list with four nodes */
	struct s_node *listHead = create_node();
	struct s_node *currNode = listHead;
	struct s_node *listNode1 = currNode;

	(*currNode).next = create_node();
	currNode = (*currNode).next;
	struct s_node *listNode2 = currNode;

	(*currNode).next = create_node();
	currNode = (*currNode).next;
	struct s_node *listNode3 = currNode;

	(*currNode).next = create_node();
	currNode = (*currNode).next;
	struct s_node *listNode4 = currNode;

	/* Assign references to each node in the list */
	(*listNode1).reference = listNode3;
	(*listNode2).reference = listNode4;
	(*listNode3).reference = listNode2;
	(*listNode4).reference = listNode1;

	/* Deep copy list */
	struct s_node *listCopy = duplicate_list(listHead);

	/* Print the original list out */
	printf("Printing original list:\n");
	print_list(listHead);

	/* Print the copied list out */
	printf("Printing duplicated list:\n");
	print_list(listCopy);

	/* Delete orig list and print */
	printf("Deleting orig list:\n");
	delete_list(listHead);
	listHead = 0;
	printf("Printing original list:\n");
	print_list(listHead);
	printf("Printing duplicated list:\n");
	print_list(listCopy);

	return 0;
}