#include <stdio.h>#include <time.h>#define max 16//2의 거듭제곱(본 프로그램에서 계산 가능한 배열의 최대크기)void ArraySet(int n, int (*a)[max], int (*b)[max], int (*c)[max]);void ArrayMulti(int n, int (*a)[max], int (*b)[max], int (*c)[max]);void Strassen(int n, int (*a)[max], int (*b)[max], int (*c)[max]);void ArrayPrint(int n, int (*tmp)[max]);int main(){int a[max][max];int b[max][max];int c[max][max];int n;printf("2의 거듭제곱을 입력하세요 = ");scanf("%d",&n);ArraySet(n, a, b, c);printf("A 배열n");ArrayPrint(n, a);printf("nB 배열n");ArrayPrint(n, b);ArrayMulti(n, a, b, c);//표준 알고리즘 호출printf("n////표준 알고리즘 완료////n");printf("C 배열(결과)n");ArrayPrint(n, c);//배열 출력Strassen(n, a, b, c);//쉬트라센 알고리즘 호출printf("n////쉬트라센 알고리즘 완료////n");printf("C 배열(결과)n");ArrayPrint(n, c);//배열 출력return 0;}
⊙ 산술식을 트리로 구성하고 infix, prefix, postfix 방식으로 접근1) 해결방법: 우선 한 개의 다항식을 입력받아 배열에 넣고 앞에서부터 순차적으로 검색하며 배열에 push함과 동시에 트리를 구성한다.이 때 사용되는 배열은 연산자 배열과 피연산자 배열로 연산자 배열에는 char형의 값이 들어가며 피연산자 배열에는 그때 그때 생성된 피연산자 노드의 주소값이 들어간다. 이때의 자료형은 정의된 구조체의 포인터 형이다.다항식을 배열에 push 할 때의 판단 기준은 피연산자는 조건없이 순차적으로 push 되며, 연산자의 경우는 연산자의 우선순위를 따져 이전에 넣은 연산자의 우선순위가 지금 넣으려는 연산자의 우선순위보다 높거나 같으면 이전에 넣은 연산자의 계산을 선행하는 동시에 배열에서 제거(pop)해 준 후 새로운 연산자를 push 한다. 이때 이전에 넣은 연산자의 계산을 선행한다는 것은 해당 연산자에 대한 한 개의 루트와 두 개의 차일드를 가지는 트리를 구성하여 결과를 나타낸다고 생각하고 피연산자의 배열에 push 한다. 이 때 연산자 우선순위를 판단하는 과정은 각 연산자에 레벨을 부여하는 방법을 사용하였다. 그리고 괄호연산의 경우는 괄호 안에서의 계산 과정도 밖에서의 과정과 같으나 연산자 우선순위에 관계없이 괄호 안의 연산자에 대한 트리 생성을 선행해 줌으로서 해결해 주었다.그리고 다항식의 배열로의 적용이 끝났다 하더라도 트리 생성이 끝난 것이 아니다. 단지 연산자 우선순위에 따라 먼저 해주어야 하는 계산은 먼저 해주어 결국에는 우선순위가 낮은 연산자부터 높은 연산자로 배열되도록 하는 과정이었고, 다항식의 배열에 대입이 끝난 후에는 가장 오른쪽에 있는 연산자부터 트리를 생성해 주면 된다. 이때 새로 생성된 트리는 계속 위로 붙어 누적되므로 트리를 가리키던 헤더 값도 계속 변하게 된다.infix, prefix, postfix로의 접근은 재귀함수를 사용하여 노드의 주소값을 찾아 들어가며 leaf노드의 링크값은 모두 NULL인것 을 참고하여 종료조건을 만X]; // 연산자 스택 배열struct node* ope2[MAX]; // 피연산자 스택 배열(노드의 주소값을 가짐)////////////////////////////////////////////////////////////////////////////////////////스택에 필요한 함수들void pushOpe1(char a);void popOpe1();int full1();int empty1();int top1=0;void pushOpe2(struct node* a);struct node* popOpe2();int full2();int empty2();int top2=0;//////////////////////////////////////////////////////////////////////////////////////void changeTree(); // 산술식을 트리로 만들어 주는 함수struct node* makeNode(char); // 하나의 노드를 만들어 주소값을 반환void makeOneTree(char); // 한개의 루트 아래 두개의 subtree를 가지는 트리 생성void inOrder(struct node*); // infix 출력void preOrder(struct node*); // prefix 출력void postOrder(struct node*); // postfix 출력int isp(char a); // 연산자에 대한 level값 반환int main(){printf("산술식 입력 = ");gets(poly);changeTree();printf("changeTree is OKn");printf("inOrder = ");inOrder(tree);printf("npreOrder = ");preOrder(tree);printf("npostOrder = ");postOrder(tree);printf("n");return 0;}{코딩 리스트void changeTree(){int i;char data;for(i=0;i=isp(c(sizeof(struct node)); // 추가할 노드 생성newnode->value=a;newnode->alink=NULL;newnode->blink=NULL;return newnode; // 생성된 노드의 주소값 반환}{코딩 리스트void makeOneTree(char a){struct node* onenode;onenode=makeNode(a);tree=onenode;onenode->blink=popOpe2();onenode->alink=popOpe2();pushOpe2(onenode);}void inOrder(struct node* T){if(T!=NULL){inOrder(T->alink);printf("%c", T->value);inOrder(T->blink);}}void preOrder(struct node* T){if(T!=NULL){printf("%c", T->value);preOrder(T->alink);preOrder(T->blink);}}void postOrder(struct node* T){if(T!=NULL){postOrder(T->alink);postOrder(T->blink);printf("%c", T->value);}}int isp(char a){if(a=='(') return 0;else if(a=='+' || a=='-') return 1;else if(a=='*' || a=='/') return 2;else return 3;}//////////////////////////////////////////////////////////////////////////////////////// 배열을 이용한 스택 1void pushOpe1(char a){if(!full1()){ope1[top1]=a;top1++;}else printf("Ope1 is FULLn");}{코딩 리스트void popOpe1(){if(!empty1()){top1--;}else printf("Ope1 is EMPTYn");}int full1(){if(top택 2void pushOpe2(struct node* a){if(!full2()){ope2[top2]=a;top2++;}else printf("Ope2 is FULLn");}struct node* popOpe2(){struct node* tmp;if(!empty2()){top2--;tmp=ope2[top2];}else printf("Ope2 is EMPTYn");return tmp;}int full2(){if(top2==MAX) return 1;else return 0;}int empty2(){if(top2==0) return 1;else return 0;}//////////////////////////////////////////////////////////////////////////////////////{MakeFileall : polytreepolytree : polytree.ogcc -o polytree polytree.opolytree.o : polytree.cgcc -c polytree.cclean :-del polytree.exe3) 결 과{결 과D:sourceds>polytree산술식 입력 = a+b*(c-d)/echangeTree is OKinOrder = a+b*c-d/epreOrder = +a/*b-cdepostOrder = abcd-*e/+D:sourceds>D:sourceds>polytree산술식 입력 = a*(b+c/d)-echangeTree is OKinOrder = a*b+c/d-epreOrder = -*a+b/cdepostOrder = abcd/+*e-D:sourceds>D:sourceds>polytree산술식 입력 = (a+b)*(c-d)/(e+f)changeTree is OKinOrder = a+b*c-d/e+fpreOrder = /*+ab-cd+efpostOrder = ab+cd-*ef+/D:sourceds>D:sourceds>polytree산술식 입력 = a*b+(c*(d-e))/fchange졌는지.. 어디서 잘못되었는지 정확히 확인할 수 있는 방법이 없어 원인을 찾는데 조금 애를 먹었으나 프로그램 실행과정을 추적하여 이유를 찾아 보니 연산자 우선순위에 의해 미리 만들어진 트리를 다시 피연산자에 넣어주는 과정에서 차일드 노드들의 정보가 떨어져 나가게 되었다는걸 알았다. 그래서 생각한 방법이 우선 모든 피연산자는 다항식에서 스캔할 때부터 노드화를 시켜주고 배열에는 생성한 노드의 주소값이 들어가게 되는 것이다. 이렇게 되면 생성된 트리를 피연산자 스택에 넣어줄 때에도 root의 주소값만 넣어주면 됨으로 이용에 문제가 없게 되었다.그리고 추가로 개선한 부분은 본래 ( ) 연산에 대한 부분에서 문제에서는 항상 괄호 안에 두 개의 피연산자와 한 개의 연산자만을 넣어 계산을 했었다. 그래서 아무생각없이 ) 를 만나면 그 전에 입력된 연산자에 대한 트리를 생성하고 배열을 두 번 pop하면 ( 까지 삭제되어 문제가 없다고 생각하였다. 하지만 실제 식에서는 괄호 안에 한 개의 연산자만 있으란 법이 없고 또 이중, 삼중 괄호가 없으란 법이 없다. 이를 해결하기 위한 방법이 끝을 인식하게 하는 법이다. 우선 괄호 안의 식이 아무리 길어져도 계산의 방법은 괄호가 없는 산술식이랑 같다. 결과적으로 연산자 우선순위를 참조한 배열에 입력 후에는 오른쪽에 있는 연산자부터 트리화 시켜주는 것이다. 이때 트리화 시켜주며 연산자 배열의 참조가 ( 가 오게되면 트리화 시켜주는것을 중단하고 배열에서 ( 를 pop 해주면 된다.본 프로그램을 짜면서 느낀점은 프로그램을 짜기 전에 전체적으로 프로그램을 어떻게 짜야 할지 미리 생각을 하고 조금 더 넓고 깨어있는 생각을 해야 한다는 것이다. 우선 항상 프로그램을 짜기 시작할때는 내가 짜는 프로그램을 어떤 방식으로 짜야할지 진지하게 생각해보기보다는 대충.. 이렇게 하면 될까? 하는 생각으로 시작하고.. 안되면 계속 여기저기 수정하다 보니 내가 짠 프로그램이지만 대체 이부분이 왜 이렇게 되고 왜 이렇게 수정한건지 알수가 없게 되었다. 결국 다 지각한다.
⊙ Prim's algorithm으로 찾은 Minimum Spanning Tree1) 해결방법- 기본 원리: 모든 노드를 한번씩 거치되 가장 짧은 가중치를 갖는 노드를 거친다. 단 싸이클을 이루지 말아야 한다.- 알고리즘 탐색 방법: 우선 가중치가 가장 작은 엣지를 찾은 후 Prim's 알고리즘에 의하여 지금까지 검색된 모든 노드가 가지고 있는 인접노드 중 가중치가 가장 작은 노드를 찾아 엣지를 연결한다. 이때 새로운 노드 접근시 인접한 노드를 찾아가므로 모든 노드는 단 한번씩만 검색이 되는데 노드에 접근을 할때마다 접근상태를 표시해 주면 검색의 완료를 "모든노드의 접근이 끝났을 때" 로 해줄 수 있다.- 싸이클 검사 방법: 모든 노드의 검색은 한번만 이루어 지므로 새로운 인접노드가 내가 이미 검색한 노드이면 싸이클을 이룬다.2) 코딩 리스트 및 makefile의 내용{코딩 리스트#include#define node 20#define edge 24void SpanningTree();void prim();void print_Min_edge(int a, int b);void Print_Edge(int a);int E[node][node];int freeE[node];int alink, blink, min_eg=1000, sum=0;int main(){int i, j;for(i=0;i