GitLab system status is available here and here

Commit 51cc04e5 authored by Jiaqi Duan's avatar Jiaqi Duan
Browse files

Update Graph.c

parents
/*
Name: Jiaqi Duan
CruzID: jduan10
Source file Name: Graph.c
IDE: XCode
*/
# include <stdio.h>
# include <stdlib.h>
# include "Graph.h"
/* ------------------------------ Structs ----------------------------------*/
typedef struct GraphObj{
int order; // the number of vetices in the graph
int size; // the number of edges in the graph
int source; // the source element
int* discover; // the discover time
int* finish; // the finish time
int* parent; // the parent array
int* distance; // the distance array
int* color; // set 0->w 1->g or 2->b
List* adjList; // The adjacent list
}GraphObj;
/* ---------------------- Constructors-Destructors --------------------------*/
// returns a Graph pointing to a newly created GraphObj representing a graph having n vertices and no edges.
Graph newGraph(int n){
Graph G = malloc(sizeof(GraphObj));
G->order = n; // where n is the number of vertices in graph
G->size = 0;
G->source = NIL;
G->discover = malloc((n+1) * sizeof(int));
G->finish = malloc((n+1) * sizeof(int)); // set it INF using loop // integer array of n + 1
G->parent = malloc((n+1) * sizeof(int));
G->distance = malloc((n+1) * sizeof(int)); // set it INF using loop // integer array of n + 1
G->color = malloc((n+1) * sizeof(int)); // the default color would be white, which is 0
G->adjList = malloc((n+1) * sizeof(List)); // list of list
for(int i = 0; i < n+1; i++){
G->distance[i] = INF;
G->color[i] = 0;
G->parent[i] = NIL;
G->discover[i] = UNDEF;
G->finish[i] = UNDEF;
G->adjList[i] = newList();
}
return(G);
}
// frees all heap memory associated with a graph and sets its Graph argument to NULL.
void freeGraph(Graph* pG){
if(pG != NULL && *pG != NULL){
// free every array
free((*pG)->parent);
free((*pG)->distance);
free((*pG)->color);
free((*pG)->discover);
free((*pG)->finish);
int n = (*pG)->order;
// free every list
for(int i = 0; i < n+1; i++){
freeList(&(*pG)->adjList[i]);
}
free((*pG)->adjList);
free(*pG);
*pG = NULL;
}
}
/* --------------------------- Access functions -------------------------------*/
// returns the number of vertices in G
int getOrder(Graph G){
if(G == NULL){
printf("Graph Error: calling getOrder() on NULL Graph reference\n");
exit(EXIT_FAILURE);
}
return(G->order);
}
// return the size of edges
int getSize(Graph G){
if(G == NULL){
printf("Graph Error: calling getSize() on NULL Graph reference\n");
exit(EXIT_FAILURE);
}
return(G->size);
}
// returns the source vertex most recently used in function BFS(),
// or NIL if BFS() has not yet been called.
int getSource(Graph G){
if(G == NULL){
printf("Graph Error: calling getSource() on NULL Graph reference\n");
exit(EXIT_FAILURE);
}
return(G->source);
}
// return the parent of vertex u in the Breadth-First tree created by BFS(),
// or NIL if BFS() has not yet been called.
// have the precondition 1<=u<=n=getOrder(G)
int getParent(Graph G, int u){
if(G == NULL){
printf("Graph Error: calling getParent() on NULL Graph reference\n");
exit(EXIT_FAILURE);
}
if(1 > u || u > getOrder(G)){
printf("Graph Error: calling getParent() precondition don't meet for 1 ≤ u ≤ getOrder(G)\n");
exit(EXIT_FAILURE);
}
return(G->parent[u]);
}
// The discover of vertices will be undefined before DFS is called.
// have the precondition 1<=u<=n=getOrder(G)
int getDiscover(Graph G, int u){
if(G == NULL){
printf("Graph Error: calling getDiscover() on NULL Graph reference\n");
exit(EXIT_FAILURE);
}
if(1 > u || u > getOrder(G)){
printf("Graph Error: calling getDiscover() precondition don't meet for 1 ≤ u ≤ getOrder(G)\n");
exit(EXIT_FAILURE);
}
return(G->discover[u]);
}
// The finish times of vertices will be undefined before DFS is called.
// have the precondition 1<=u<=n=getOrder(G)
int getFinish(Graph G, int u){
if(G == NULL){
printf("Graph Error: calling getFinish() on NULL Graph reference\n");
exit(EXIT_FAILURE);
}
if(1 > u || u > getOrder(G)){
printf("Graph Error: calling getFinish() precondition don't meet for 1 ≤ u ≤ getOrder(G)\n");
exit(EXIT_FAILURE);
}
return(G->finish[u]);
}
// returns the distance from the most recent BFS source to vertex u,
// or INF if BFS() has not yet been called.
// have the precondition 1 ≤ u ≤ getOrder(G).
int getDist(Graph G, int u){
if(G == NULL){
printf("Graph Error: calling getDist() on NULL Graph reference\n");
exit(EXIT_FAILURE);
}
if(1 > u || u > getOrder(G)){
printf("Graph Error: calling getDist() precondition don't meet for 1 ≤ u ≤ getOrder(G)\n");
exit(EXIT_FAILURE);
}
return(G->distance[u]);
}
// appends to the List L the vertices of a shortest path in G from source to u,
// or appends to L the value NIL if no such path exists.
// getPath() has the precondition getSource(G)!=NIL, so BFS() must be called before getPath().
// have the precondition 1 ≤ u ≤ getOrder(G).
void getPath(List L, Graph G, int u){
if(G == NULL){
printf("Graph Error: calling getPath() on NULL Graph reference\n");
exit(EXIT_FAILURE);
}
if(L == NULL){
printf("Graph Error: calling getPath() on NULL List reference\n");
exit(EXIT_FAILURE);
}
if(getSource(G) == NIL){
printf("Graph Error: calling getPath() precondition don't meet for getSource(G)! = NIL\n");
exit(EXIT_FAILURE);
}
if(1 > u || u > getOrder(G)){
printf("Graph Error: calling getPath() precondition don't meet for 1 ≤ u ≤ getOrder(G)\n");
exit(EXIT_FAILURE);
}
if(G->source == u){ // if u is source then append source to L
append(L, u);
}else if(G->parent[u] == NIL){ // if parent of u is nil, append nil
append(L, NIL);
}else{
getPath(L, G, G->parent[u]);
append(L, u);
}
}
/* ------------------------ Manipulation procedures ----------------------------*/
// deletes all edges of G, restoring it to its original (no edge) state.
// (This is called a null graph in graph theory literature).
void makeNull(Graph G){
if(G == NULL){
printf("Graph Error: calling makeNull() on NULL Graph reference\n");
exit(EXIT_FAILURE);
}
int n = G->order; // where n is the number of vertices in graph
for(int i = 0; i < n+1; i++){
G->distance[i] = INF;
G->color[i] = 0;
G->parent[i] = NIL;
clearList(G->adjList[i]);
G->size = 0; // the number of edges size
G->source = NIL; // the source element
G->discover[i] = UNDEF;
G->finish[i] = UNDEF;
}
}
// The function have the responsibility to maintain adjacency list in numerical increasing sorted order
// inserts a new directed edge from u to v, i.e. v is added to the adjacency List of u (but not u to
// the adjacency List of v).
// have the precondition that their two int arguments must lie in the range 1 to getOrder(G).
void addArc(Graph G, int u, int v){
if(G == NULL){
printf("Graph Error: calling addArc() on NULL Graph reference\n");
exit(EXIT_FAILURE);
}
if(1 > u || u > getOrder(G)){
printf("Graph Error: calling addArc() precondition don't meet for 1 ≤ u ≤ getOrder(G)\n");
exit(EXIT_FAILURE);
}
if(1 > v || v > getOrder(G)){
printf("Graph Error: calling addArc() precondition don't meet for 1 ≤ v ≤ getOrder(G)\n");
exit(EXIT_FAILURE);
}
// add value v to the adjacency List of u, and sort them in increasing number order
if(isEmpty(G->adjList[u])){ // if the adjacent list is empty just append v to the adjList[u]
append(G->adjList[u], v);
}else{ // if it's not empty then compare
moveFront(G->adjList[u]); // move the cursor to the front
while(indexElem(G->adjList[u]) >= 0 && indexElem(G->adjList[u]) <= length(G->adjList[u]) - 1){ // while the cursor is on the list
if(get(G->adjList[u]) > v){ // if the cursor element is bigger than v
insertBefore(G->adjList[u], v); // then u should be before the cursor element
break;
}else if(get(G->adjList[u]) < v){ // if the cursor element is smaller than v
if(indexElem(G->adjList[u]) == length(G->adjList[u]) - 1 ){ // if the cursor is pointing the last element
append(G->adjList[u], v); // then append value v to the end of the list
break;
}
}else{ // if the cursor element equal to v
insertAfter(G->adjList[u], v); // then u should be after/before(chose after in this case) the cursor element
break;
}
moveNext(G->adjList[u]); // move the cursor to the next element
}
}
G->size++;
}
// The function have the responsibility to maintain adjacency list in numerical increasing sorted order
// inserts a new edge joining u to v, i.e. u is added to the adjacency List of v, and v to the adjacency
// List of u.
// Your program is required to maintain these lists in sorted order by increasing labels.
// have the precondition that their two int arguments must lie in the range 1 to getOrder(G).
// Pre: 1<=u<=n, 1<=v<=n
void addEdge(Graph G, int u, int v){
if(G == NULL){
printf("Graph Error: calling addEdge() on NULL Graph reference\n");
exit(EXIT_FAILURE);
}
if(1 > u || u > getOrder(G)){
printf("Graph Error: calling addEdge() precondition don't meet for 1 ≤ u ≤ getOrder(G)\n");
exit(EXIT_FAILURE);
}
if(1 > v || v > getOrder(G)){
printf("Graph Error: calling addEdge() precondition don't meet for 1 ≤ v ≤ getOrder(G)\n");
exit(EXIT_FAILURE);
}
// add value u to the adjacency List of v, and sort them in increasing number order
if(isEmpty(G->adjList[v])){ // if the adjacent list is empty just append u to the adjList[v]
append(G->adjList[v], u);
}else{ // if it's not empty then compare
moveFront(G->adjList[v]); // move the cursor to the front
while(indexElem(G->adjList[v]) >= 0 && indexElem(G->adjList[v]) <= length(G->adjList[v]) - 1){ // while the cursor is on the list
if(get(G->adjList[v]) > u){ // if the cursor element is bigger than u
insertBefore(G->adjList[v], u); // then u should be before the cursor element
break;
}else if(get(G->adjList[v]) < u){ // if the cursor element is smaller than u
if(indexElem(G->adjList[v]) == length(G->adjList[v]) - 1 ){ // if the cursor is pointing the last element
append(G->adjList[v], u); // then append value u to the end of the list
break;
}
}else{ // if the cursor element equal to u
insertAfter(G->adjList[v], u); // then u should be after/before(chose after in this case) the cursor element
break;
}
moveNext(G->adjList[v]); // move the cursor to the next element
}
}
// add value v to the adjacency List of u, and sort them in increasing number order
if(isEmpty(G->adjList[u])){ // if the adjacent list is empty just append v to the adjList[u]
append(G->adjList[u], v);
}else{ // if it's not empty then compare
moveFront(G->adjList[u]); // move the cursor to the front
while(indexElem(G->adjList[u]) >= 0 && indexElem(G->adjList[u]) <= length(G->adjList[u]) - 1){ // while the cursor is on the list
if(get(G->adjList[u]) > v){ // if the cursor element is bigger than v
insertBefore(G->adjList[u], v); // then u should be before the cursor element
break;
}else if(get(G->adjList[u]) < v){ // if the cursor element is smaller than v
if(indexElem(G->adjList[u]) == length(G->adjList[u]) - 1 ){ // if the cursor is pointing the last element
append(G->adjList[u], v); // then append value v to the end of the list
break;
}
}else{ // if the cursor element equal to v
insertAfter(G->adjList[u], v); // then u should be after/before(chose after in this case) the cursor element
break;
}
moveNext(G->adjList[u]); // move the cursor to the next element
}
}
G->size++;
}
// runs the BFS algorithm on the Graph G with source s, setting the color, distance, parent,
// and source fields of G accordingly.
void BFS(Graph G, int s){
if(G == NULL){
printf("Graph Error: calling BFS() on NULL Graph reference\n");
exit(EXIT_FAILURE);
}
int n = getOrder(G);
int x = 0;
List Q = NULL; // Use as Queue
for(int i = 1; i <= n; i++){ // for every x other than the source s
if(i == s){
continue; // continue
}else{
G->color[i] = 0;
G->distance[i] = INF;
G->parent[i] = NIL;
x = i; // get the i value to x
}
}
// discover the source s
G->color[s] = 1;
G->distance[s] = 0;
G->parent[s] = NIL;
G->source = s; // labeling the source to be s
Q = newList(); // make a new empty list for Queue
append(Q, s); // enqueue s into Q
while(!isEmpty(Q)){
// dequeue
x = front(Q);
deleteFront(Q);
// for i in adj[x]
moveFront(G->adjList[x]);
// using cursor to move in adjList
while(indexElem(G->adjList[x]) >= 0 && indexElem(G->adjList[x]) <= length(G->adjList[x]) - 1){
int y = get(G->adjList[x]); // get the data of the cursor
if(G->color[y] == 0){ // if color[i] == white, which means that i is undiscovered
G->color[y] = 1; // discover i
G->distance[y] = G->distance[x] + 1;
G->parent[y] = x;
append(Q, y);
}
moveNext(G->adjList[x]);
}
G->color[x] = 2;
}
}
// DFS() has two preconditions: (You are required to check the first precondition but not the second.)
// (i) length(S) == n --> length(S) == getOrder(G) and
// (ii) S contains some permutation of the integers {1, 2, ... , n} where n = getOrder(G).
void DFS(Graph G, List S){
if(G == NULL){
printf("Graph Error: calling DFS() on NULL Graph reference\n");
exit(EXIT_FAILURE);
}
if(length(S) != getOrder(G)){
printf("Graph Error: calling DFS() on length(S) == getOrder(G)\n");
exit(EXIT_FAILURE);
}
int n = getOrder(G);
int u = 0; // for index elemnent
int time; // ptr for time
// initializing everything in graph
for(int i = 1; i <= n; i++){ // for all x in V(G)
G->color[i] = 0; // color[x] = white
G->parent[i] = NIL; // p[x] = nil
G->discover[i] = UNDEF; // make discover time undefined
G->finish[i] = UNDEF; // make finish time undefined
}
time = 0;
// main loop of DFS
// for loop moving thru S starting at the front
for(moveFront(S); indexElem(S) >= 0; moveNext(S)){
u = get(S); // get the element of S (cursor elem)
if(G->color[u] == 0){ //if color is white
visit(G, S, &time, u); // visit(G, element of S, time)
}
}
// emptying the stack with un-needed element
for(int i = 1; i <= n; i++){ // 1 thru 8 variable that r first into the list
deleteBack(S);
}
}
/* ----------------------------- Other operations -------------------------------*/
// will be used in DFS function
// Pre: G not equal to NULL, time ptr not equal to NULL, and 1 ≤ u ≤ getOrder(G)
void visit(Graph G, List S, int* time, int u){
if(G == NULL){
printf("Graph Error: calling visit() on NULL Graph reference\n");
exit(EXIT_FAILURE);
}
if(1 > u || u > getOrder(G)){
printf("Graph Error: calling visit() precondition don't meet for 1 ≤ u ≤ getOrder(G)\n");
exit(EXIT_FAILURE);
}
int i = 0;
List L = NULL;
G->discover[u] = (++*time); // discover x
G->color[u] = 1; // color[x] = gray
L = G->adjList[u];
moveFront(L);
if(length(L) > 0){
while(indexElem(L) >= 0 && indexElem(L) <= length(L) - 1){
i = get(L);
if(G->color[i] == 0){ // if color[i] == white
G->parent[i] = u;
visit(G, S, time, i);
}
moveNext(L);
}
}
G->color[u] = 2; // color[x] = black
G->finish[u] = (++*time); // finish x
prepend(S, u);
}
// returns a reference to a new graph object representing the transpose of G
// could be considered constructors since they create new graph objects
Graph transpose(Graph G){
if(G == NULL){
printf("Graph Error: calling transpose() on NULL Graph reference\n");
exit(EXIT_FAILURE);
}
if(getOrder(G) == 0){
printf("Graph Error: calling transpose() on getOrder(G) == 0\n");
exit(EXIT_FAILURE);
}
Graph newG = NULL;
newG = newGraph(getOrder(G));
newG->size = G->size;
newG->source = G->source;
// walk through the Graph
for(int i = 0; i < getOrder(G)+1; i++){
moveFront(G->adjList[i]);
// walk throught the List
while(indexElem(G->adjList[i]) >= 0 && indexElem(G->adjList[i]) <= length(G->adjList[i]) - 1){
addArc(newG, get(G->adjList[i]), i);
moveNext(G->adjList[i]);
}
}
return newG;
}
// returns a reference to a new graph that is a copy of G
// could be considered constructors since they create new graph objects
Graph copyGraph(Graph G){
if(G == NULL){
printf("Graph Error: calling copyGraph() on NULL Graph reference\n");
exit(EXIT_FAILURE);
}
if(getOrder(G) == 0){
printf("Graph Error: calling copyGraph() on getOrder(G) == 0\n");
exit(EXIT_FAILURE);
}
Graph newG = NULL;
newG = newGraph(getOrder(G));
newG->size = G->size;
newG->source = G->source;
for(int i = 0; i < getOrder(G)+1; i++){ // for all x in V(G)
newG->distance[i] = G->distance[i];
newG->color[i] = G->color[i];
newG->parent[i] = G->parent[i];
newG->discover[i] = G->discover[i];
newG->finish[i] = G->finish[i];
newG->adjList[i] = copyList(G->adjList[i]);
}
return newG;
}
// prints the adjacency list representation of G to the file pointed to by out.
// The format of this representation should match the above examples,
// so all that is required by the client is a single call to printGraph().
void printGraph(FILE* out, Graph G){
if(G == NULL){
printf("Graph Error: calling printGraph() on NULL Graph reference\n");
exit(EXIT_FAILURE);
}
// check if BFS(G,s) was run
int n = getOrder(G); // get the number of vertices in Graph
for(int i = 1; i <= n; i++){
fprintf(out, "%d: ", i);
printList(out, G->adjList[i]);
// fprintf(out, "\n"); // newline
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment