중화사전망 - 자전 검색 - 연결된 목록을 사용하여 호프만 트리의 파스칼 코드 구축 [긴급]
연결된 목록을 사용하여 호프만 트리의 파스칼 코드 구축 [긴급]
/* 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); //노드 해제
}
}