#include #include //메모리 할당 매크로 함수#define MALLOC(p, s)if (!((p) = malloc(s))) {fprintf(stderr, "Insufficient memory");exit(EXIT_FAILURE);}typedef struct node * treePointer;typedef struct node{int data;treePointer leftChild, rightChild;}; // root 포인터 생성treePointer root;void inorder(treePointer ptr){ /* 중위 트리 순회 함수*/if (ptr) {inorder(ptr->leftChild);printf("%d ", ptr->data);inorder(ptr->rightChild);}}treePointer search(treePointer root, int key){ /* 키값이 key인 노드에 대한 포인터를 반환함.그런 노드가 없는 경우에는 NULL을 반환 */if (!root) return NULL;if (key == root->data) return root;if (key < root->data)return search(root->leftChild, key);return search(root->rightChild, key);}treePointer modifiedSearch(treePointer lead, int key){ /* key값이 존재하면 NULL, 없으면 뒤 따라온 trail 노드 리턴 */treePointer trail=NULL;while (lead) {trail = lead;if(keydata) lead = lead->leftChild;else if(key==lead->data) return NULL;else lead = lead->rightChild;}return trail;}void insert (treePointer *node, int key){/* 트리내의 노드가 key를 가리키고 있으면 아무 일도 하지 않음;그렇지 않은 경우는 data=key인 새 노드를 첨가 */// 루트에서 시작하여 key를 찾아라treePointer ptr, temp = modifiedSearch(*node, key);if(temp || !(*node)) {/* key값이 트리에 없다면 */MALLOC(ptr, sizeof(*ptr));ptr->data = key;ptr->leftChild = ptr->rightChild = NULL;if(*node) //공백 트리가 아니면// temp가 가리키는 자식 노드에 ptr넣음if(keydata) temp->leftChild = ptr;else temp->rightChild = ptr;else *node = ptr; // 값이 없었다면 첫노드 생성}}int deleteFull(treePointer* ptr){int leftMax;treePointer temp;/*기준 노드의 왼쪽 sub트리 중 가장 큰 값의 노드를 찾아 왼쪽 자식 링크를 변경*/if ((*ptr)->rightChild==NULL) {leftMax = (*ptr)->data; //삭제될 노드의 왼쪽 sub트리 중 값이 가장 큰 노드를 저장temp = *ptr;//sub트리 가장 오른쪽 단말 노드를 temp에 저장*ptr = (*ptr)->leftChild;/* *ptr은 삭제될 트리의 왼쪽 sub트리 중 가장 큰 값을 갖고 있는 노드이며자신의 원래 값은 leftMax에 저장해 반환시키고 자신의 위치에는 자신의왼쪽 자식을 넣는다.*/free(temp); // 연결이 끊어진 동적메모리를 해제시켜 메모리 낭비를 없앤다.return leftMax; // leftMax 노드 값을 리턴해 삭제할 노드에 값을 바꿔준다.} else {//오른쪽 자식이 있을 경우 deleteFull()에 오른쪽 자식을 넣고 재호출한다.return deleteFull(&(*ptr)->rightChild);}}void deleteNode(treePointer* lead, int key){treePointer temp;if (*lead) {//삭제될 key과 트리의 데이터를 비교 작으면 왼쪽 sub트리로 함수 재호출if (key < (*lead)->data) {deleteNode(&(*lead)->leftChild, key);}//삭제될 key과 트리의 데이터를 비교 크면 오른쪽 sub트리로 함수 재호출else if (key > (*lead)->data) {deleteNode(&(*lead)->rightChild, key);}//트리 노드의 좌/우 자식이 없으면 *lead를 삭제하고 NULL값으로 초기화else if ((*lead)->leftChild==NULL && (*lead)->rightChild==NULL){free(*lead);*lead = NULL;}//트리 노드의 왼쪽 자식이 없으면 *lead에 오른쪽 자식을 넣고 자신은 삭제else if ((*lead)->leftChild==NULL){temp=*lead;*lead = (*lead)->rightChild;free(temp);}//트리 노드의 오른쪽 자식이 없으면 *lead에 왼쪽 자식을 넣고 자신은 삭제else if ((*lead)->rightChild==NULL) {temp=*lead;*lead = (*lead)->leftChild;free(temp);}// 트리에 좌/우 자식이 모두 붙어 있는 경우else {(*lead)->data = deleteFull(&(*lead)->leftChild);//삭제될 위치에 왼쪽 sub트리 중에 가장 큰 값으로 바꾼다.}}return;}int main(){int menuSelect, count, inputKey, i;while(1){printf("n┏━━━━━━━━━━━━━━━━━━━━┓");printf("n┃ (1) 삽입 (2) 삭제 (3) 출력 (4) 종료 ┃");printf("n┗━━━━━━━━━━━━━━━━━━━━┛");printf("n 메뉴 선택 : ");scanf("%d", &menuSelect); // 메뉴선택값 입력받음switch(menuSelect){case 1:// 삽입printf(" 삽입하려는 키 갯수 : ");scanf("%d", &count);printf(" 삽입하려는 키 값 : ");for (i=0 ; i < count ; i++){scanf("%d",&inputKey);insert (&root, inputKey);}break;case 2:// 삭제if(root!=NULL) { // 트리가 비어있지 않을경우printf(" 삭제하려는 키 갯수 : ");scanf("%d", &count);printf(" 삭제하려는 키 값 : ");for (i=0 ; i < count ; i++){scanf("%d", &inputKey);deleteNode(&root, inputKey);}}else printf(" 트리가 생성되어 있지 않습니다.n");break;case 3:// 출력if(root!=NULL) { // 트리가 비어있지 않을경우printf(" 삽입된 데이터의 중위순회 탐색 출력 : ");
컴퓨터시스템구조론 W. Stallings(김종현역) 연습문제3장 4, 7, 11, 15, 174장 1, 2, 8, 10, 15, 18, 195장 2, 3, 4, 86장 2, 3, 510장 3, 7, 911장 2, 4, 6, 812장 1, 3, 8, 103.4 16비트 주소(예를 들어 프로그램 카운터와 주소 레지스터들의 폭이 16비트라고 가정)를 발생시키고, 16비트 데이터 버스를 가진 가상적인 마이크로 프로세서가 있다고 하자.a. 만약 프로세서가 ‘16비트 기억장치’와 접속되어 있다면, 프로세서가 직접 액세스할 수 있는 최대 기억장치 주소 공간은 얼마인가?☞ 216=64Kbytes의 주소 공간을 직접 액세스할 수 있다.b. 만약 프로세서가 ‘8비트 기억장치’와 접속되어 있다면, 프로세서가 직접 액세스할 수 있는 최대 기억장치 주소 공간은 얼마인가?☞ 216=64Kbytes의 주소 공간을 직접 액세스할 수 있다. 다만 ‘8비트 기억장치’와 접속이 되어 있는 프로세서라면 액세스를 할 때 한번에 전송할 수 있는 폭이 1byte이지만 ‘16비트 기억장치’와 접속이 되어 있는 프로세서의 경우엔 1byte나 16bytes 워드 단위로 전송 가능하다.c. 이 프로세서가 분리된 ‘I/O 공간’을 액세스할 수 있게 되려면, 어떤 구조적 특성들을 가져야 하는가?☞ 분리된 I/O 신호를 발생시키는 명령어 셋이 필요하고, 이 신호를 전달하려면 최소한 하나의 출력 핀이 필요하다.d. 만약 입력 및 출력 명령어가 8비트 I/O포트 번호를 지정할 수 있다면, 이 마이크로프로세서가 몇 개의 8비트 I/O포트들을 지원할 수 있는가? 16비트 I/O포트는 몇 개를 지원할 수 있는가? 그 이유를 설명하라.☞ 각각 28=256bytes의 I/O 포트를 지원할 수 있다. 입력과 출력은 다른 명령어 신호를 발생시키는 것으로 구분하는 것이므로 16비트 I/O포트 또한 216=64Kbytes만큼의 포트를 지원할 수 있다.3.7 각각 8비트와 16비트 폭의 외부 데이터 버스를 가진 두개의 마이크로 프로세1/f는 100ns가 되므로 읽기 명령어 사이클은 3×100ns=300ns가 필요하다.b. 기억장치 데이터는 늦어도 언제까지 버스에 실어야 하는가? 데이터 선의 안정을 위하여 20ns의 여유를 주라.☞ T3의 후반부 중간(약 3/4지점)에 떨어지기 시작한다고 하였고 읽기 명령어 사이클은 3클럭이 필요하므로 약 275ns초 이전에는 데이터를 버스에 실어야 한다는 계산이 나온다. 그러나 데이터 선의 안정을 위하여 20ns의 여유를 주라고 하였으므로 275-20=255ns 즉, 늦어도 255ns까지는 데이터를 실어야 한다.3.15 인텔 8088 마이크로프로세서는 그림 3.19와 유사한 읽기 버스 타이밍을 가지고 있지만, 네 개의 프로세서 클록 사이클을 필요로 한다. 유효 데이터가 버스에 실려 있어야 하는 시간이 네 번째 프로세서 클록 사이클까지로 연장되었다. 프로세서 사이클 율은 8MHz라고 가정한다.a. 최대 데이터 전송률은 얼마인가?☞ 1/f = 1/8×106 = 0.000000125 = 125ns 즉, t는 125ns초가 되고, 1번 데이터를 읽는데 4클럭이 소요되므로 8×106/4=2MB/s가 최대 데이터 전송률이 된다.b. 한 바이트가 전송될 때마다 대기 상태가 하나씩 삽입되어야 한다고 가정했을 때, 위의 문제를 반복하라.☞ 1바이트가 전송되는데 사용되는 클럭 사이클 수가 4개에서 다음 데이터가 전송되기 전에 대기 클럭 사이클 수가 1클럭이 추가되므로 연속된 데이터를 전송하기 위해서는 총 5클럭이 필요하게 되므로 최대 데이터 전송률은 8×106/5=1.6MB/s가 된다.3.17 버스 사이클 주기가 16 비트 마이크로프로세서의 경우와 동일한 32 비트 마이크로프로세서가 있다고 하자. 평균적으로, 오퍼랜드와 명령어의 20%는 길이가 32 비트이고, 40%는 길이가 16비트이며, 40%는 길이가 8 비트밖에 되지 않는다고 가정하자. 32 비트 마이크로프로세서를 이용하여 명령어들과 오퍼랜드들을 인출할 때 어느 정도(성능) 개선을 얻을 수 있는지 구하라.☞ 100개512개(213/24=29)의 라인으로 구성되어 있고, 2-way 세트이므로 256개(512/2)의 세트로 구성되어 있음을 알 수 있다. 따라서 8비트의 세트공간이 필요하고, 메인메모리의 공간이 64Mbytes(226)이므로 4M(226/24=222)개의 블록으로 구성되어 있다. 이것을 직접 주소지정하기 위해서는 22비트의 공간이 필요하므로 테그는 22-8=14비트의 공간이 필요하다.다음은 이를 표로 나타낸 것이다.14bit8bit4bitTAGSETWORD4.8a. 주기억장치 주소 16비트가 태그, 라인 번호 및 바이트 번호로 어떻게 나누어지는가?☞ 주기억장치가 8K(216/23)개의 블록들을 가지고 있으므로, 13비트 주소(8K=213)에 의하여 각 바이트가 직접 주소지정 될 수 있다. 워드의 길이는 각 블록의 크기가 8바이트라고 했으므로 3비트의 공간이 필요하고, 32개의 라인으로 이루어진 직전 사상 캐시이므로 5비트(25=32)의 라인공간이 필요하다. 마지막으로 테그는 13-5=8비트로 표현 될 수 있다.다음은 이를 표로 나타낸 것이다.8bit5bit3bitTAGLINEWORDb. 다음 각 주소의 바이트들이 어느 라인에 저장되는가?☞ 앞에 8비트는 테그 비트이므로 제외하고, 나머지 8비트 중 맨 뒤의 3비트는 offset이므로 제외하면 다음 표처럼 저장되는 라인들을 정리할 수 있다.주 소LINE 비트저장 되는 라인0001 0001 0001 1011000113번째 라인1100 0011 0011 0100001106번째 라인1101 0000 0001 1101000113번째 라인1010 1010 1010 10101010121번째 라인c. 0001 1010 0001 1010 번지의 바이트가 캐시에 저장되었다고 가정하자. 그것과 같이 저장되는 다른 바이트들의 주소들은 어떤 것인가?☞ 블록 단위로 저장되므로 해당하는 주소의 offset이 000부터 111까지의 주소들이 저장된다. 즉, 0001 1010 0001 1000 ~ 0001 1010 0001 1111 의 주소ication 명령을 반복적으로 수행하고, 바로 그 옆에 있는 a[1]에 접근하여 같은 작업을 하고 있다.b. 앞의 코드에 존재하는 시간적 지역성의 예를 보여라.☞ 처음 루프를 돌때 배열 a[0]은 10번 연속적으로 계속 메모리에 접근하게 된다.4.18a. 1Mbytes 주기억장치의 가격은 얼마인가?☞ 1byte=8bit이므로 10-5×8×106=10×8=80$b. 캐시 기술을 사용하여 1Mbyte의 주기억장치를 구성한다면 가격은 얼마가 되는가?☞ 1byte=8bit이므로 10-4×8×106=102×8=800$c. 유효 액세스 시간(effective access time)이 캐시 액세스 시간보다 10% 더 길게 하려면, 적중률 H는 얼마가 되어야 하는가?☞ H는 더 빠른 기억장치에서 찾을 수 있는 비율이므로 유효 액세스 시간이 캐시 액세스 시간보다 10% 더 길게 한다는 소리는 한 단어를 읽는데 걸리는 평균시간이 100×1.1=110ns가 되게 H를 결정하라는 의미이므로 다음과 같이 계산하면 된다.110ns=(100ns×H)+(1-H)(1200ns+100ns) = 1190/1200 = 0.9916즉, 캐시 적중률이 0.9916이 되어야 한다.4.19☞ (0.9×20ns)+(0.1×0.6)(20ns+60ns)+(0.1×0.4)(20ns+60ns+12×106)= (0.9×20ns)+(0.06×80ns)+(0.04×12000080) = 480026ns5.2☞ 1ms의 시간 중 재충전을 위해서 소요되는 시간은 64×150ns=9600ns가 소요된다. 따라서 1×10-3ms당 9600×10-9ns의 비율을 계산하면 9600×10-9/1×10-3 = 0.0096 즉, 0.96%를 재충전에 할당해야 한다.5.3a. 기억장치 사이클 시간은 60ns+40ns=100ns이고, 100ns 당 1bit를 전송하는 것이므로 데이터 율은 1/100ns가 된다.b. 1비트를 전송할 때 데이터 율이 1/100ns이므로 32/100ns가 된다.5.4☞ 8Mbytes의 메모리 용량이 있으므로라서 이 두개의 평균을 구하면 299.99/2=149.995ms가 평균 탐색시간(seek time)이 된다.b. 7200rpm으로 회전한다는 소리는 분당 7200번 회전한다는 소리이므로 1바퀴를 회전할 때 걸리는 시간이 1/(7200/60)=0.0083=8.33ms가 걸린다. 따라서 평균 지연시간은 4.165msc. n/rN을 구하는 것이므로 (1/600)×(60/7200)=0.01389msd. 전체 평균 시간은 seek time+latency+transfer time=149.995+4.165+0.01389=154.17389ms6.5☞ 호스트 시스템의 요구 패턴과 데이터의 배치에 영향을 받는다. 만약에 하나의 I/O 요구의 크기가 스트립보다 더 크고 여러 개의 연속적인 논리 스트립으로 구성되어 있다면, 그 요구에 대한 n개의 스트립들이 병렬로 액세스 될 수 있어서 I/O전송시간이 줄어들 것이다. 하지만 I/O의 요구가 스트립보다 작고 여러 개의 I/O에서 요구를 한다면 디스크 스트라이핑을 한 디스크는 병렬처리를 할 수 없고, 추가적으로 논리적 디스크 공간과 물리적 디스크 공간 사이의 매핑을 위해 배열 관리 소프트웨어를 통해 디스크에 접근하게 되므로 스트라이핑을 하지 않은 디스크에서 더 뛰어난 성능을 보일 것이다.10.3a. 부호없는(Unsigned) : 0 ~ 255 (28 -1)b. 부호-크기(Sign-magnitude) : -127 ~ 127 (-0과 +0이 있기때문)c. 1의 보수 : -127 ~ 127 (-0과 +0이 있기때문)d. 2의 보수 : -128 ~ 127 (0이 하나로 나오므로)e. 부호없는 밀집형 10진수 : 0 ~ 99 (2진수 4자리가 십진수 1자리를 나타내기때문)f. 부호있는 밀집형 10진수 : -9 ~ +9 (최상위 nibble이 부호비트를 위해 사용되기때문)10.7a. Y번지엔 현재 0이 들어있고, 누산기엔 현재 K라는 값이 들어있다고 가정하자. 또한 X번지엔 현재 X값이 들어있다고 가정하자. 다음과 같이 하면된다.Instructi10