중화사전망 - 자전 검색 - 연결된 목록을 사용하여 호프만 트리의 파스칼 코드 구축 [긴급]

연결된 목록을 사용하여 호프만 트리의 파스칼 코드 구축 [긴급]

/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

/* Subject [3] 호프만 인코딩 파일 압축 기능 */

/* */

/* */

/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

# include & ltstdio.h & gt// 헤더 파일 포함

# include & ltstdlib.h & gt

# include & ltstring.h & gt

# include & ltconio.h & gt

# include & ltiostream.h & gt

# definemax _ single code10//단일 문자의 최대 코드 길이

# definemax _ string10000//인코딩할 문자열의 최대 길이.

#define MAX_CODESTRING 50000 // 생성된 바이너리 코드의 최대 길이.

#define MAX_WORDS 1000 // 문자열에서 인코딩할 최대 문자 수입니다.

# END_TREE 30000 // 트리 섹션에 저장된 종료자 정의

# 경로 50 // 경로의 최대 문자 수를 정의합니다

/* = = = = = = = 데이터 구조 정의 부분 = = = = = */

/* Huffman 트리 구조 정의. 여기서 next 필드는 연결된 테이블의 작업에 사용됩니다 */

Typedef 구조 Huffmantree

{

Char ch// 문자 섹션

Int 무게 //노드 가중치

Int 태그; //트리에 추가할지 여부를 표시합니다.

Struct Huffmantree *parent, *lchild, *rchild, * next

}HTNode, * LinkTree

/* * * * 인코딩 사전 구조 정의 * * * */

Typedef struct //ch 는 문자 값이고 code[] 는 문자의 호프만 인코딩입니다.

{

Char ch// 문자 섹션

Charcode [max _ single code]; //인코딩 섹션

} CodeDictionary

/* = = = = = = 하위 기능 = = = = = = */

/* = = = = = = = = = = = = = = = = = 압축 기능 구현 부분 = = = = = = = = = = = = = = = = = = = = =

/* 기능: 읽기. TXT 파일을 string[] */

Void readFile(char *string)

{

FILE * FP

Int I;;

Char ch// 읽은 문자를 기록합니다

Charpath [path]; //텍스트 파일 경로 읽기

Cout & lt& lt "입력한 주소입니다. 압축할 txt 파일: (확장자 필요 없음) "

가져오기 (경로);

If ((FP = fopen (strcat (path, ") 입니다. Txt ")," r ")= = null)// 파일을 읽기 전용으로 엽니다.

{

Cout & lt& lt" \ n 경로가 잘못되었습니다! \ n "<& ltendl

Getch ();

반환;

}

Ch = fgetc (FP); //루프 파일의 문자를 배열 문자열 [] 에 입력합니다.

For(I = 0;; Ch! = EOFi++)

{

String [I] = ch;

Ch = fgetc (FP);

}

String[I]=' \ 0 ';'; //배열 끝에 끝 플래그 "\o" 를 추가합니다.

Fclose (FP);

}

/* 함수는 문자열 [] 의 문자를 처리하고, 같은 문자를 삭제하고, 가중치를 증가시킵니다 */

링크 트리 어셈블리 가중치 (char *string)

{

Int I = 0;; //파일 문자열 아래 첨자

링크 트리 나무; //헤드 포인터

LinkTree ptr, beforeptr// 포인터 및 그 앞 포인터 만들기

HTNode * 노드 :

If ((tree = (link tree) malloc (sizeof (htnode)) = = null)//연결된 테이블의 헤더 노드 생성.

반환 NULL// 메모리가 부족합니다

나무->; Next = NULL

For(I = 0;; String[i]! ='\0'; I++)

{

Ptr = 나무;

Beforeptr = tree

If ((node = (htnode *) malloc (sizeof (htnode)) = = null)

반환 NULL// 새 노드 만들기

노드->; Next = NULL

노드->; Parent = NULL

노드->; Lchild = NULL

노드->; Rchild = NULL

노드->; 마크 = 0;

노드->; Ch = string [I];

노드->; 무게 =1;

If (나무-> Next==NULL) // 첫 번째 비헤드 노드인 경우

나무->; Next = 노드 :

기타

{

Ptr = 트리-> 다음으로,

그리고 (ptr&& ptr-> Ch! = 노드->; Ch) // 같은 문자 찾기

{

Ptr = ptr-& gt;; 다음으로,

Beforeptr = beforeptr-> 다음으로,

}

Ptr&& ptr-> 인 경우 Ch = = 노드-> Ch) // 연결된 목록에 있는 한 노드의 문자가 새 노드의 문자와 같은 경우

{

Ptr-& gt;; 웨이트++; //이 노드의 가중치에 1 을 더합니다.

무료 (노드);

}

Else // 연결된 목록에 새 노드를 삽입한 후

{

노드->; Next = beforeptr-> 다음으로,

Beforeptr-> Next = 노드 :

}

}

}

트리로 돌아가기 //헤드 포인터 반환

}

/* 함수: 연결된 목록의 가중치 문자를 작은 것부터 큰 것까지 배열하고 연결된 목록에 입력합니다. */

링크 트리 정렬 노드 (링크 트리 트리)

{

링크 트리 헤더; //헤드 포인터

LinkTree ph, beforeph// 포인터 및 그 앞 포인터 만들기

링크 트리 각도;

If ((head = (link tree) malloc (sizeof (htnode)) = = null)//새 연결된 테이블의 헤더 노드를 생성합니다.

NULL 을 반환합니다

헤드->; Next = NULL

Ph = 헤드;

Beforeph = head

While (나무->; 다음)

{

Pt = 트리-> 다음으로, //조작된 연결된 목록의 헤드 노드를 가져옵니다.

나무->; Next = pt-& gt;; 다음으로,

Pt-& gt;; Next = NULL

Ph = 헤드->; 다음으로,

Beforeph = head

If (헤드-> Next==NULL)

헤드->; Next = pt// 현재 작동 체인 테이블의 헤더 노드를 생성합니다.

기타

{

그리고 (ph& & ampph->; 무게 & ltpt-& gt;; Weight) // 조작된 노드를 해당 위치에 삽입합니다.

{

Ph = ph->; 다음으로,

Before ph = before ph-& gt;; 다음으로,

}

Pt-& gt;; Next = before ph-& gt;; 다음으로,

이전 ph-& gt;; Next = pt

}

}

무료 (나무); //가중치 트리 해제

돌아오는 길 //정렬된 헤드 포인터를 반환합니다.

}

/* 정렬 된 연결된 목록을 사용하여 호프만 트리 만들기 */

링크 트리 생성 트리 (링크 트리 트리)

{

LinkTree pt, q, beforept

HTNode * newnode

For (pt = tree-> 다음으로 q = pt-& gt;; 다음으로, Pt! = NULL & amp& ampq! = NULLpt = tree-& gt;; 다음으로 q = pt-& gt;; 다음)

//pt 및 Q 의 초기 값은 헤드 노드 뒤의 두 노드, 즉 최소 가중치 노드입니다.

{

나무->; Next = q-& gt;; 다음으로, //가장 작은 두 개의 노드를 제거합니다.

Q->; Next = NULL

Pt-& gt;; Next = NULL

If ((new node = (htnode *) malloc (sizeof (htnode)) = = null)

//호프만 트리의 중간 노드로 새 노드를 요청합니다.

NULL 을 반환합니다

새 노드-> Next = NULL

새 노드-> 마크 = 0; //표식

새 노드-> Lchild = pt// 연결된 헤더 노드 뒤에 있는 두 노드를 새 노드의 왼쪽 및 오른쪽 하위 노드로 사용합니다.

새 노드-> Rchild = q;;

Pt-& gt;; Parent = newnode

Q->; Parent = newnode

새 노드-> 가중치 = pt-& gt;; 무게+q->; 무게; //가중치는 1 차 하위 구성요소 가중치의 합과 같습니다.

Pt = 트리-> 다음으로,

Beforept = tree

만약 (pt! = NULL & amp& amppt-& gt;; 무게>= new node-& gt;; 무게)

{

새 노드-> Next = before pt-& gt;; 다음으로, //원래 연결된 목록의 해당 위치에 새 노드를 삽입합니다.

Beforept->; Next = newnode

}

기타

{

그리고 (pt! = NULL & amp& amppt-& gt;; 무게< 새 노드-> Weight)// newnode 노드가 삽입된 위치를 순환합니다.

{

Pt = pt-& gt;; 다음으로,

Before pt = before pt-& gt;; 다음으로,

}

새 노드-> Next = before pt-& gt;; 다음으로,

Beforept->; Next = newnode

}

}

Return (나무-> 다음);

}

/* 호프만 트리를 인코딩하고 키워드를 */

Void codeHTree(LinkTree 트리, CodeDictionary *codedictionary)

{

Int index=0, k = 0;;

Charcode [max _ single code]; //호프만 코드는 각 문자를 계산하는 데 사용됩니다.

LinkTree ptr = tree// 트리의 루트 노드에서 시작

If(ptr==NULL)

{

Cout & lt& lt "압축할 파일이 비어 있습니다! \ n "<& ltendl

종료 (0);

}

기타

{

While (ptr->; 어린이와 건강. & ampptr-& gt;; 칠드 & amp& ampptr-& gt;; 마크 = = 0)

{

While (ptr->; 어린이와 건강. & ampptr-& gt;; L child-& gt;; 마크 = = 0)

{

코드 [인덱스++] =' 0'; //왼쪽 분기 코드는 0 입니다.

Ptr = ptr-& gt;; Lchild

만약 (! Ptr-& gt;; 어린이와 건강. & amp! Ptr-& gt;; Archid)// 왼쪽 및 오른쪽 하위 노드가 없는 경우 리프 노드입니다.

{

Ptr-& gt;; 마크 =1; //기호는 문자가 인코딩되었음을 나타냅니다.

코드 [index] =' \ 0'; //인코딩 0- 1 문자열 끝

코드 디렉토리 [k]. Ch = ptr-& gt;; Ch; //사전에 문자 값 지정

For (색인 = 0; 코드 [색인]! ='\0'; Index++)

코드 디렉토리 [k]. 코드 [색인] = 코드 [색인]; //사전에 코드 값 할당

코드 디렉토리 [k]. 코드 [index] =' \ 0';

K++;+;

Ptr = 나무; //포인터 재설정

색인 = 0;

}

}

If (ptr-> 칠드 & amp& ampptr-& gt;; Rchild-& gt;; 마크 = = 0)

{

Ptr = ptr-& gt;; Rchild

코드 [인덱스++] ='1'; //오른쪽 지코드는 1 입니다.

}

만약 (! Ptr-& gt;; 어린이와 건강. & amp! Ptr-& gt;; Archid)// 왼쪽 및 오른쪽 하위 노드가 없는 경우 리프 노드입니다.

{

Ptr-& gt;; 마크 =1;

코드 [인덱스++] =' \ 0';

코드 디렉토리 [k]. Ch = ptr-& gt;; Ch; //사전에 문자 값 지정

For (색인 = 0; 코드 [색인]! ='\0'; Index++)

코드 디렉토리 [k]. 코드 [색인] = 코드 [색인]; //사전에 코드 값 할당

코드 디렉토리 [k]. 코드 [index] =' \ 0';

K++;+;

Ptr = 나무;

색인 = 0;

}

If (ptr-> L child-& gt;; 마크 = =1& & ampptr-& gt;; Rchild-& gt;; 마크 = =1)//왼쪽 및 오른쪽 하위 플래그가 표시된 경우 ,

{

Ptr-& gt;; 마크 =1;

Ptr = 나무;

색인 = 0;

}

}

}

Cout & lt& lt" \ n "<& ltendl

}

/* 전체 문자열을 0- 1 의 문자열로 변환 */

Void compressString(char *string, CodeDictionary *codedictionary, char *codestring)

{

Int i=0, j=0, k=0, m;

While(string[i]) // 전체 파일 문자열이 끝나지 않았을 때.

{

While(string[i]! = 코드 디렉토리 [j]. Ch & amp& ampj & ltMAX_WORDS)

//해당 문자와 동일한 문자를 찾습니다.

J++;+;

If (string [I] = = code dictionary [j]. Ch)// 해당 문자와 동일한 문자를 찾은 경우 ,

For(m = 0;; 코드 디렉토리 [j]. 코드 [m]; M++, k++)

코드 문자열 [k] = 코드 디렉토리 [j]. 코드 [m];

J = 0;; //사전 재설정

I++;+;

}

Codestring[k]=' \ 0 ';'; //끝 표시

}

/* 가중치별로 정렬된 연결된 목록 및 인코딩 문자열 저장 */

Void write code (링크 트리, char *string)

{

FILE * FP

Int I;;

Int 무게 //기록된 중량을 기록합니다.

Char ch// 기록된 문자

링크 트리 p;

Charpath [path]; //0- 1 코드 파일 쓰기 경로

Cout & lt& lt "압축 저장 경로와 파일 이름을 입력하십시오: (확장자 필요 없음)"

가져오기 (경로);

If((fp=fopen(strcat(path, ") 입니다. Wp ")," w+")= = NULL)

{

Cout & lt& lt" \ n 파일 경로 오류! \ n "<& ltendl

Getch ();

반환;

}

P = 트리-> 다음으로,

/* 무게별로 각 부분을 배열하여 파일의 첫 부분에 씁니다. */

하다

{

Ch = p-& gt;; Ch;

가중치 =p- > 무게

Fprintf(fp, "%c%d", ch, weight);

P = p-& gt;; 다음으로,

} while (p);

Fprintf (FP, "%c% d",'', end _ tree);

Fseek(fp, sizeof(char),1); //디코딩할 때 연결된 테이블과 코드를 구분하는 구분 비트를 남겨둡니다.

/*0- 1 코드 쓰기 파일의 마지막 부분 */

For (I =1; String [I-1]; I++)

{

If (string [I-1] = ='1')

{

Ch<& lt= 1;

Ch+=1;

}

If(string[i- 1]=='0')

{

Ch<& lt= 1;

Ch+= 0;;

}

다음 경우 (i%8==0)

Fputc(ch, FP);

}

Cout & lt& lt" \ n 압축 성공! \ n "<& ltendl

Getch ();

Fclose (FP);

}

/* 호프만 나무가 차지하는 공간 확보 */

Void deleteTree (링크 트리)

{

링크 트리 ptr = 트리

중간 주파수 (ptr)

{

트리 삭제 (ptr-& gt;; L child); //먼저 왼쪽 하위 트리 처리로 돌아갑니다

트리 삭제 (ptr-& gt;; Rchild); //첫 번째로 처리된 오른쪽 하위 트리를 반환합니다

무료 (PTR); //노드 해제

}

}