Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Structures I Structures allow grouping of data items. For example, the following declaration creates a new type struct record. struct record { char *name; long int studentId; char *major; } I Now we can use the new type to declare variables, arrays, pointers etc. For example: struct struct struct struct record record record record r; /* static declaration */ students1[1000]; /* a static or fixed 1-dim. array*/ students2[100][1000]; /* a static 2-dim. array*/ *student; /* a pointer to a struct record */ n = 1000; student = (struct record *) malloc(sizeof(struct record)*n); for (i=0; i<n; i++) { student[i].studentId = i; /* give a fake id */ student[i].major = NULL; /* no major yet */ student[i].name = (char *) malloc(sizeof(char)*MAX_NAME_LENGTH); } Structures I Structures allow grouping of data items. struct node { int keyValue; struct node * next; } struct node *head; head=(struct node *)malloc(sizeof(struct node)); *head.keyValue = 10; /* the following is equivalent to the above */ head->keyValue = 10; I head->next = ???? /* undefined */ Use typedef for simplifying declarations. For example: typedef struct node Node; typedef struct node *NodePtr; I I Discuss example C-examples/singlyLinkedLists Discuss example C-examples/doublyLinkedLists Example with Structures (contd.) I A simple declaration of a node in a singly linked list. struct node { int item; struct node *next; } struct node *addAtFront(struct node *list, struct node *newNode); printList (struct node *list); node = (struct node *) malloc(sizeof(struct node)); node->item = 0; node->next = NULL; I Use typedef to simplify. typedef struct node Node; tyepdef struct node * NodePtr; struct node { int item; struct node *next; } NodePtr addAtFront(NodePtr list, NodePtr newnode); printList (NodePtr list); node = (NodePtr) malloc(sizeof(Node)); node->item = 0; node->next = NULL; Singly Linked List #ifndef __SINGLYLINKEDLIST_H #define __SINGLYLINKEDLIST_H /* C-examples/singlyLinkedList/SinglyLinkedList.h */ #include <stdio.h> #include <stdlib.h> typedef struct node Node; typedef struct node * NodePtr; typedef int ItemType; struct node { ItemType item; NodePtr next; }; /* prototypes */ NodePtr addAtFront(NodePtr L, NodePtr node); NodePtr reverseList(NodePtr L); void printList(NodePtr L); #endif /* __SINGLYLINKEDLIST_H */ Singly Linked List (contd.) /* C-examples/singlyLinkedList/SinglyLinkedList.h */ /* SinglyLinkedList.c: Functions to manipulate a linked list. #include <stdio.h> #include <stdlib.h> #include "SinglyLinkedList.h" NodePtr addAtFront(NodePtr L, NodePtr node) { if (node == NULL) return L; if (L == NULL) { L = node; node->next = NULL; } else { node->next = L; L = node; } return L; } NodePtr reverseList(NodePtr L) { NodePtr list = NULL; while (L != NULL) { NodePtr tmp = L; L = L->next; tmp->next = list; list = tmp; } return list; } void printList(NodePtr L) { while (L) { printf(" %d -->",L->item); L = L->next; } printf(" NULL \n"); } */ Using the Singly Linked List class /* C-examples/singlyLinkedList/TestLists.c */ #include <stdio.h> #include <stdlib.h> #include "SinglyLinkedList.h" int main(int argc, char **argv) { int i; int n; NodePtr list, node; if (argc != 2) { fprintf(stderr, "Usage: %s <list size> \n",argv[0]); exit(1); } n = atoi(argv[1]); list = NULL; for (i=0; i<n; i++) { node = (NodePtr) malloc(sizeof(Node)); node->item = i; if (node == NULL) { printf("Error allocating node for linked list\n"); exit(1); } list = addAtFront(list, node); } printList(list); list=reverseList(list); printList(list); exit(0); } An (Almost) Generic Doubly Linked List An example of an “almost” generic doubly linked lists where each item stored in a node is also a pointer to a structure instead of a primitive type. This example can be found in the directory: C-examples/doublyLinkedLists/almost-generic [amit@dslamit almost-generic]$ ls common.h Job.c Job.h List.c List.h main.c Makefile Node.c Node.h TestList.c [amit@dslamit almost-generic]$ cat common.h #ifndef __COMMON_H #define __COMMON_H #include <string.h> #define TRUE 1 #define FALSE 0 typedef int Boolean; #endif /* __COMMON_H */ Job.h: Example with Structures (contd.) #ifndef __JOB_H #define __JOB_H #include <stdio.h> #include <stdlib.h> #include "common.h" #define MAXPID_DIGITS 10 typedef struct job * JobPtr; struct job { int pid; char *info; }; JobPtr createJob (int, char *); char *toString(JobPtr); #endif /* __JOB_H */ Job.c: Example with Structures (contd.) #include "Job.h" JobPtr createJob(int pid, char *info) { JobPtr newJob = (JobPtr) malloc (sizeof(struct job)); newJob->pid = pid; newJob->info = (char *) malloc(sizeof(char)*(strlen(info)+1)); strcpy(newJob->info, info); return newJob; } char *toString(JobPtr node) { char *temp; temp = (char *)malloc(sizeof(char)* (strlen(node->info)+1+MAXPID_DIGITS+4)); sprintf(temp, "[%d] %s", node->pid, node->info); return temp; } Node.h: Example with Structures (contd.) #ifndef __NODE_H #define __NODE_H #include #include #include #include <stdio.h> <stdlib.h> "common.h" "Job.h" typedef struct node Node; typedef struct node * NodePtr; struct node { JobPtr data; NodePtr next; NodePtr prev; }; NodePtr createNode (JobPtr data); #endif /* __NODE_H */ Node.c: Example with Structures (contd.) #include "Node.h" NodePtr createNode(JobPtr data) { NodePtr newNode = (NodePtr) malloc (sizeof(Node)); newNode->next = NULL; newNode->prev = NULL; newNode->data = data; return newNode; } List.h: Example with Structures (contd.) /* List.h: Defines #ifndef __LIST_H #define __LIST_H the interface for a doubly-linked list. */ #include <stdio.h> #include <stdlib.h> #include "common.h" #include "Node.h" typedef struct list List; typedef struct list * ListPtr; struct list { int size; NodePtr head; NodePtr tail; }; /* prototypes of public methods */ ListPtr createList(); /* constructor */ int getSize(ListPtr L); Boolean isEmpty(ListPtr L); void addAtFront(ListPtr list, NodePtr node); void addAtRear(ListPtr list, NodePtr node); NodePtr removeFront(ListPtr list); NodePtr removeRear(ListPtr list); void reverseList(ListPtr L); void printList(ListPtr L); #endif /* __LIST_H */ List.c: Example with Structures (contd.) #include <stdio.h> #include <stdlib.h> #include "List.h" /*list.c Contains functions to manipulate a doubly-linked list.*/ /* private methods */ static NodePtr reverse(NodePtr L); static void print(NodePtr node); ListPtr createList() { ListPtr list = (ListPtr) malloc(sizeof(ListPtr)); list->size = 0; list->head = NULL; list->tail = NULL; return list; } int getSize(ListPtr L) { return L->size; } Boolean isEmpty(ListPtr L) { if (L->size == 0) return TRUE; else return FALSE; } void addAtFront(ListPtr list, NodePtr node) { if (list == NULL) return; if (node == NULL) return; list->size++; node->next = list->head; node->prev = NULL; if (list->head == NULL) { list->head = node; list->tail = node; } else { list->head->prev = node; list->head = node; } } void addAtRear(ListPtr list, NodePtr node) { } NodePtr removeFront(ListPtr list) { return NULL; } NodePtr removeRear(ListPtr list) { return NULL; } void reverseList(ListPtr L) { L->tail = L->head; L->head = reverse (L->head); } static NodePtr reverse(NodePtr L) { NodePtr list = NULL; while (L != NULL) { NodePtr tmp = L; L = L->next; if (L != NULL) L->prev = tmp; tmp->next = list; tmp->prev = L; list = tmp; } return list; } void printList(ListPtr L) { print(L->head); } static void print(NodePtr node) { while (node) { printf(" %s -->",toString(node->data)); node = node->next; } printf(" NULL \n"); } main.c: Example with Structures (contd.) #include <stdio.h> #include <stdlib.h> #include "common.h" #include "Job.h" #include "Node.h" #include "List.h" int main(int argc, char **argv) { int i; int n; NodePtr node; JobPtr job; ListPtr list; if (argc != 2) { fprintf(stderr, "Usage: %s <list size> \n",argv[0]); exit(1); } n = atoi(argv[1]); list = createList(); for (i=0; i<n; i++) { job = createJob(i, "cmd args"); node = createNode(job); addAtFront(list, node); } printList(list); reverseList(list); printList(list); reverseList(list); printList(list); exit(0); } A Screenshot of Doubly-linked List A screen shot of doubly-linked list with a sentinel node at the front. Other Data Structures I I Binary Tree. To declare a binary tree, we can use something like the following declaration. typedef struct treeNode treeNode; typedef struct treeNode *treeNodePtr; struct treeNode { int key; struct info *data; treeNodePtr left; treeNodePtr right; } M-ary Tree. Here is an example of a tree where each node can have up to MAX DEGREE=M child nodes. typedef struct treeNode treeNode; typedef struct treeNode *treeNodePtr; struct treeNode { int key; struct info *data; treeNodePtr child[MAX_DEGREE]; } Other Data Structures I Hash table. Here is an example of a hash table where each bucket is represented by a linked list. typedef struct listNode listNode; typedef struct listNode *listNodePtr; struct listNode { listNodePtr next; struct info *data; } listNode ** hashTable; hashTable = (listNode **) malloc(sizeof(listNodePtr)*n); for (i=0; i<n; i++) { hashTable[i] = NULL; } Recommended Exercises I I I Develop a complete header file for a “generic” Binary Search Tree class in C. What operations would you want to provide? How would you store data in the Binary Search Tree? We will at least need methods for searching, inserting, deleting, inorder traversal among others. Develop a complete header file for a “generic” Hash Table that uses hashing with chaining. Use the doubly linked list class for the list part. We will at least need a hash method and methods for inserting, searching, deleting an object. Develop a complete header file for a StringTokenizer class that gives functionality similar to the java.util.StringTokenizer class. Note: In order to create a real generic list, tree or hashtable we need to use function pointers. See the section on function pointers later in these notes for a real generic list example.