에서 재판 : 해시 분할과 정복 - 10 첫 번째 IP 통계의 가장 높은 수는 대용량 데이터를 표시
다음 코드는 다음과 같습니다
// 대규모 데이터 (10) IP 미리 출현의 가장 높은 수를 찾기 // 알고리즘 사고, 분할 및 정복 // IP 로그 파일 크기 10 GB의 약 억 IP, 64에 대한 MB의 메모리 제한 //는 IP 로그 파일을 작은 해시 파일에 IP 모듈 (500), (500) // 동일한 IP는 같은 파일을 해시 에, // 평균 작은 파일 20메가바이트 64MB의 각 // 다시 각 IP에 대한 이진 트리 사용 작은 파일의 수를 계산 // 이진 트리 탐색 및 IP의 발생의 최대 수 반환 이, ^ 32 (2)되는 중복 IP를 생성 할 수 있도록 2 ^ (32) IP 생성해야하기 때문에 // IP를 약을 // 64기가바이트 문서, 파일의 10기가바이트을 보장하기 위해 중복 IP를 생성 할 수 100.100.100.100 - // 설정된 IP 섹션 0.0.0.0 //에만 507 개의 파일을 열 수는 fopen () 마스터 레코드 : 포스트 스크립트 @를 작은 파일 500 (점)로 구분 파일 후 // 다른 컴퓨터 (규칙) 네트워크를 통해 전송이 작은 파일로 계산 될 수 후 맵리 듀스 구글에서 작동 유사 메인 프로그램 // 결과, 즉 반환 사용법 #include <stdio를. H> #INCLUDE <stdlib.h> #INCLUDE <time.h> #INCLUDE <io.h> // 통로 () 사용법 #include <string.h> CONST의 INT의 NUM은 = 1000000; // 천만 수동 NUM 수정 부호 INT ITON (CHAR * IP)을 상기 서브 - 포인트 표기 // IP 어드레스 정수로 공극 ntoi (NUM 부호 INT, CHAR * IP) 의 INT fileexist (숯불 * 경로); // 파일을 결정하는 존재 무효 fclose_all (파일 ** t을); // 가까운 모든 파일 (숯불 * 경로) random_write int로; // 670,000,000 무작위로 생성 된 IP에 대한 10기가바이트 hashfile에서 // 통계 가장 자주 IP 무효 COUNT (* hashfile의 문자, 부호없는 INT * 데이터, NUM 부호 * INT), 무효 정렬 (부호 INT * 최대, IP 부호 INT의 *, INT N-); // 정렬 인라인 부호 INT 해시 (서명 INT의 IP ) // 해시 함수 {창 (IP 500 %)} 의 typedef 구조체 // 노드 노드 이진 { 부호 INT IP //는 IP 부호 INT N-, 발생의 횟수 // 노드 왼쪽 *; 노드 * 오른쪽; } 노드; 메인 INT (무효) { = NULL의 파일 *] 은 FILE *의 TMPFILE [505] 의 char * 경로 = "C : \\ ip_data.dat"; 숯 hashfile [50] 숯 BUF [20이다] 부호 추가, 데이터하는 int , N-] 부호 INT IP [10] 최대 [10]; // 기록 상위 10은 IP 부호 INT의 T1, T2, S, E; // 녹음 시간 INT I, J, 지금 렌, // IP의 개수 인 printf ( "S는 데이터를 생성 % \ N- \ N-"경로), 복귀 0 (! random_write (경로)) 경우 // 기록 파일은 임의로 생성 된 IP가 // == 0이 존재 접속 (), 폴더가 있는지를 판정한다 (0) == 0 액세스 ( "\\ hashfile C") IF 시스템 ( "RMDIR / S / QC : \\ hashfile"); // 작업 빌드 디렉토리; 시스템 ( "\\ hashfile MKDIR C") 시스템 ( "ATTRIB + HC : \\ hashfile"); // 숨겨진 디렉토리 =하면 fopen에서 (경로, "RT ");// 개방형 IP 로그 파일 (== NULL의) 복귀 경우에는 0 에 대한 (I = 0; I는 505 <; 내가 ++) [I]가 = NULL TMPFILE는; // IP 505 작은 해시 파일 670 백만 것이다 에서 printf ( "\의 R은 S 해시 % \ N- \ N- "경로), E = S = T1 = 클럭 (); 지금 = 0; 그동안합니다 (에 fscanf ("%의 S 'BUF) = EOF)! { 데이터 = ITON (BUF ); // IP 디지털화 추가 = 해시 (데이터); // 해시 주소, 파일 주소 계산 , sprintf와 (hashfile, "C :. hashfile \\ \\ hash_ % U ~ TMP"추가) IF (TMPFILE [추가]를 ] == NULL)이 , TMPFILE는 [추가]를하면 fopen (hashfile, "A") = sprintf와 (BUF, "% U \ N-", 데이터), 렌 =의 나 strlen (버피); // 파일은 IP에 기록됩니다 느린 디스크 읽기 및 쓰기 반복 에 fwrite (BUF 렌 ,. 1 TMPFILE [추가를]); 이제 ++; E = 클럭 (); IF (E - S>1000) 진행 상황을 계산하기 // { printf와 (현 ( "0.2F %의 \의 T의 \ r을 진행 %% '*) / NUM 100.0) S = E; } } (에) FCLOSE; fclose_all (TMPFILE) (패스)를 제거; // 모든 작은 파일 통계 컴퓨터 처리 복수 일 수 있고, 가장 높은 IP 중복 맥스 [I]가 = 0 (; I 10 <I ++를 I = 0)에 대한 대 (I = 0; I <500; I는 ++) { 의 sprintf (hashfile "C :. hashfile \\ \\ D ~ TMP의 %의 hash_"I) IF (fileexist (hashfile)) { 의 printf ( "\ R & LT 처리 hash_ %의 D ~ TMP \ t". , I); // 작은 파일을 최대 IP의 수 계산 COUNT (hashfile, 데이터의 N- &를) 가장 큰 선택을 기록하는 아이디어 10 요소 정렬 10 // 때문에 // 너무 많은 요소가있는 경우, 당신은 삽입 정렬을 사용할 수 있습니다 스택 또는 찾을 생각 부호 INT 분 = 0xFFFFFFFF로, POS를, 대 (J = 0; J <10; J ++) { IF (최대 [J] <I) } // 디코딩 의 printf ( "% -20s % U \ N 'BUF 맥스 [I]); ; fprintf와는 (BUF 맥스 [I], "% U % -20s \ N-"기록) (- T1 "\ n ---- %의 0.3f 초 \ n을 사용하는 경우"(T2, 로그는 fprintf가 ) / 1000.0)를; 의 printf ( "\ n을 --- % 0.3f 초 사용 \ N- \ N-"(T2 - T1) / 1000.0) FCLOSE (로그) 시스템 ( "RMDIR / S / QC : \\ hashfile"), 0을 반환 ; } 공극 fclose_all (파일 ** T) 모든 파일을 닫고 // { I 값 int] 대 (I = 0; I <500; I는 ++) { IF (T [I]) { FCLOSE (T [I]) T [ I = NULL; } } } 랜덤 IP 생성 // 670,000,000, GB 10 INT의 random_write (숯 * 경로) { 은 FILE * OUT = NULL; I는, J, B 값 int; 20 buf를 숯불 것은] 숯 *의 CUR ; 부호의 INT S, E; OUT = fopen은 (경로 "중량") IF (OUT == NULL) 복귀 0] 부터 srand (시간 (NULL)); E = S = 클럭 () 대 (I = 0; I는 NUM <; I는 ++) { 클럭 = E () - IF (E S> 1,000) 진척 계산 // { 상기의 printf ( "\의 %%의 R & 0.2F %의 \의 T의 LT 진행"(I는 100.0 *) / NUM) , S = E를 } 에 대해 (J = 0; J <20이고; J ++) [J] BUF = '\ 0'; CUR = BUF; 위해 (., J <4; J = 0 J ++) { // 점 표기법이 생성되어야 0-255 값 여기서 생성 // 값은 0-101이고 ; B = RAND () 101 % , (B 'D. % "CUR)의 sprintf 그동안 (* CUR ='\ 0 ') CUR ++; } * (CUR - . 1) = '\ N-'; OUT ,. 1 BUF에 fwrite (BUF, CUR (숯 *)) } FCLOSE (교체 아웃); // 닫기 기억 수익을 1;. 부호 INT MAXN; // 입력 매개 변수 노드 * max_node; // 출력 매개 변수 무효 max_n (노드 * 트리) 가장 큰 트리 노드 N을 찾을 // } //二叉树的插入 무효 삽입 (노드 ** 나무, 부호없는 INT의 IP) { 경우 ((* 트리) == NULL) { // new_node (* 나무) = (노드 *) malloc을 (를 sizeof (노드)); (* 트리) -> IP = IP; (* 트리) -> N = 1; (* 트리) -> 왼쪽 = (* 트리) -> 우측 = NULL; } 다른 경우 ((* 트리) -> IP == IP) { (* 트리) -> N ++; 반환; } 다른 경우 (IP <(* 트리) -> IP) //左子树 삽입 (((* 트리) -> 왼쪽), IP); 다른 (((* 트리) -> 오른쪽), IP)를 삽입; //右子树 } { 경우 (트리) { 경우 (트리 -> N> maxn) { maxn = 트리 -> N; max_node = 나무; } max_n (트리 -> 좌측); max_n (트리 -> 오른쪽); } } 공극 32 파괴 (* 노드 트리) //释放树 { 경우 (트리) { 32 파괴 (트리 -> 좌측); 32 파괴 (트리 -> 오른쪽); 무료 (나무); } } //统计hashfile中次数最多的IP 공극 수 (숯의 hashfile *, * 부호 INT 데이터 부호의 INT * 않음) { = NULL의 파일 *; 노드 * 나무 = NULL; 서명되지 않은 INT의 IP; =하면 fopen에서 (hashfile "RT"); 상태 (!는 fscanf (EOF "가 % d"에서, IP) =) max_n (나무); //结果在max_node의 * N = max_node-> N; { (나무, IP)를 삽입; } (에) FCLOSE; maxn = 0; * 데이터 max_node- => IP; (나무) 32 파괴; } //插入排序 공극 정렬 (부호 * 최대 INT, IP * 부호 INT, INT 않음) { I를 INT, J; 서명되지 않은 INT의 tmpm, tmpi; 대 (I = 1; i가 N <; 내가 ++) { 경우 (최대 [I-1] <맥스 [I]) { tmpm 최대 = [I]; tmpi IP = [I]; 에 대한 (j = 1; J> 0; j--) { 경우 (최대 [J-1] <tmpm) { 맥스 [J] = 최대 [J-1]; IP [J] = IP [J-1]; } 다른 휴식; } 맥스 [J] = tmpm; IP [J] = tmpi; } } } // 정수로 스트링의 IP 주소 부호 INT ITON (* CHAR IP) { 부호의 INT R = 0; 부호의 INT t; int로 I, J; 에 대한 (j = 1 = 0; i가 <4; I ++) { sscanf를 IP (+ J '가 % d ", t); 경우 (전 3 <) 동안 (IP [J ++]! = '.'); R = R << 8; R = t +; } R를 반환; } //将整型NUM转为字符型IP 공극 ntoi (부호의 INT NUM, 숯 *의 IP) { 부호의 INT B, F; 난 CUR int로; F = 0x00FFFFFF; CUR = 0; 대 (I = 3, I> = 0; 난 ...) { B = NUM >> (I 8 *); NUM = NUM 및 F; F = F >> 8; sprintf와 IP (CUR + "U %.", b); 반면 (! IP [CUR] = '\ 0') CUR ++; \ 0 '; } } IP [CUR - 1] = '\ 0'; //判断文件存在 INT fileexist (숯 * 경로) { FILE *에서의 FP = NULL; FP가 = fopen에 (경로 "RT"); 경우 (FP) { FCLOSE (FP); 1을 반환; } 그렇지 않은 경우 0; }