二叉树 基本操作
1 //亲爱的,我又来写代码了,希望做到自己心中有思路,提纲,下笔如有神。。 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string.h> 5 #include<math.h> 6 typedef char IelemType; 7 typedef struct BiTNode{ 8 IelemType data; 9 struct BiTNode *lchild; 10 struct BiTNode *rchild; 11 12 }BiTNode,*BiTree; 13 typedef struct { 14 BiTNode *base;//栈底 15 BiTNode *top;//栈顶 16 int stacksize; 17 int length; 18 int visited; 19 }SqStack; 20 #define stack_init_size 100 21 #define stackAdd 10 22 void InitStack(SqStack &s) 23 { 24 s.base=(BiTNode *)malloc(stack_init_size*sizeof(BiTNode)); 25 if(!s.base) 26 { 27 printf("内存分配失败! "); 28 exit(0); 29 } 30 s.top=s.base; 31 s.stacksize=stack_init_size; 32 s.length=0; 33 s.visited=0; 34 } 35 36 void Push(SqStack &s,BiTree t) 37 { 38 if(s.top-s.base>=s.stacksize) 39 { 40 s.base=(BiTNode *)realloc(s.base,(s.stacksize+stackAdd)*sizeof(BiTNode)); 41 if(!s.base) 42 { 43 printf("重新分配内存失败! "); 44 exit(0); 45 } 46 s.top=s.base+s.stacksize; 47 s.stacksize+=stackAdd; 48 } 49 *s.top++=*t; 50 s.visited=0; 51 s.length++; 52 53 } 54 void Pop(SqStack &s,BiTree &t) 55 { 56 if(s.top==s.base) 57 { 58 printf("栈中无元素进来 "); 59 exit(0); 60 } 61 t=(BiTNode *)malloc(stack_init_size*sizeof(BiTNode)); 62 *t=* --s.top; 63 s.length--; 64 } 65 void GetTop(SqStack s,BiTree &t) 66 { 67 if(s.top==s.base) 68 { 69 printf("栈中无元素进来 "); 70 exit(0); 71 } 72 t=(BiTNode *)malloc(stack_init_size*sizeof(BiTNode)); 73 *t=*(s.top-1); 74 } 75 void CreateBiTree(BiTree &t,int i,int j,char ch) 76 { 77 if(i==0) 78 printf("请输入根结点: "); 79 if(i!=0&&i>=j) 80 printf("请输入%c的左结点: ",ch); 81 if(j!=0&&j>i) 82 printf("请输入%c的右结点: ",ch); 83 char e; 84 char str[20]; 85 while(1) 86 { 87 fflush(stdin);//清除缓存,这个用法要记住。 88 for(int k=0;k<20;k++) 89 { 90 str[k]=getchar(); 91 if(str[k]==' ') 92 break;//跳出for循环,注意和continue的区别 93 } 94 if(k==0) printf("请输入字符再按Enter键 "); 95 if(k==1) 96 break; 97 if(k>1) 98 printf("只能输入一个字符,请重新输入"); 99 } 100 e=str[0]; 101 if(e==' ') t=NULL; 102 else 103 { 104 if(!(t=(BiTree)malloc(sizeof(BiTNode)))) 105 exit(0); 106 t->data=e; 107 ch=t->data; 108 i++; 109 CreateBiTree(t->lchild,i,j,ch); 110 j=i;j++; 111 CreateBiTree(t->rchild,i,j,ch); 112 } 113 } 114 int TreeDepth(BiTree t,int i,int &h) 115 { 116 if(t) 117 { 118 i=i+1; 119 if(h<i) 120 h=i; 121 TreeDepth(t->lchild,i,h); 122 TreeDepth(t->rchild,i,h); 123 } 124 return h; 125 } 126 void SaveElem(BiTree t,BiTree *Q,int i) 127 { 128 if(t) 129 { 130 Q[i]=t; 131 SaveElem(t->lchild,Q,2*i); 132 SaveElem(t->rchild,Q,2*i+1); 133 } 134 } 135 void Lev_Traverse(BiTree t,int h) 136 { 137 if(t==NULL) 138 printf("sorry!目前树为空. "); 139 int k=h,i,j; 140 BiTree *Q; 141 if(!(Q=(BiTree *)malloc(int(pow(2,h)-1)*sizeof(BiTNode)))) 142 exit(0); 143 for(i=1;i<=int(pow(2,h)-1);i++){ 144 Q[i]=NULL;}//初始化的问题 145 146 SaveElem(t,Q,1); 147 for(i=1;i<=(pow(2,h)-1);i++) 148 { 149 if(int(pow(2,h))%i==0) 150 { 151 printf(" "); 152 for(j=0;j<pow(2,k-1)-1;j++){ 153 printf(" "); 154 } 155 k--; 156 } 157 //for(j=0;i<k;i++) 158 // printf("*"); 159 if(Q[i]) 160 printf("%c",Q[i]->data); 161 if(!Q[i]) 162 printf(" "); 163 for(j=0;j<pow(2,k+1)-1;j++){ 164 printf(" ");} 165 } 166 } 167 void FirstPrint(BiTree T,int i){ 168 //按先序次序(递归)访问二叉树 169 if(i==0)//现在知道为什么i需要这样传递进来了吧 170 printf(" 先序(递归)遍历结果如下: "); 171 if(T){ 172 i++; 173 printf("%-5c",T->data); //访问T 174 FirstPrint(T->lchild,i); //递归遍历左子树 175 FirstPrint(T->rchild,i); //递归遍历右子树 176 } 177 i=0; 178 }//FirstPrintBiTree 179 void MiddlePrint(BiTree T,int i){ 180 //按中序次序(递归)访问二叉树 181 if(i==0) 182 printf(" 中序(递归)遍历结果如下: "); 183 if(T){ 184 i++; 185 MiddlePrint(T->lchild,i); //递归遍历左子树 186 printf("%-5c",T->data); //访问T 187 MiddlePrint(T->rchild,i); //递归遍历右子树 188 } 189 i=0; 190 }//MiddlePrint 191 void LastPrint(BiTree T,int i){ 192 //按后序次序(递归)访问二叉树 193 if(i==0)printf(" 后序(递归)遍历结果如下: "); 194 if(T){ 195 i++; 196 LastPrint(T->lchild,i); //递归遍历左子树 197 LastPrint(T->rchild,i); //递归遍历右子树 198 printf("%-5c",T->data); //访问T 199 } 200 i=0; 201 }//LastPrint 202 203 //非递归先序遍历 204 void PreOrder(BiTree T,int i) 205 { 206 if(i==0) 207 printf("先序(非递归)遍历结果如下: "); 208 BiTree p=T,q; 209 SqStack s; 210 InitStack(s); 211 if(T) 212 { 213 while(1) 214 { 215 printf("%c",p->data); 216 Push(s,p); 217 if(p->lchild) 218 { 219 p=p->lchild; 220 } 221 else 222 break; 223 } 224 while(1) 225 { 226 Pop(s,q); 227 if(q->rchild) 228 { 229 q=q->rchild; 230 printf("%c",q->data); 231 } 232 if(s.length==0) 233 break; 234 } 235 } 236 } 237 238 //非递归中序遍历 239 void InOrder(BiTree T,int i) 240 { 241 if(i==0) 242 printf("中序(非递归)遍历结果如下: "); 243 BiTree p=T; 244 SqStack s; 245 InitStack(s); 246 while(p||(s.length!=0)) 247 { 248 if(p) 249 { 250 Push(s,p); 251 p=p->lchild; 252 } 253 else 254 { 255 Pop(s,p); 256 printf("%c",p->data);//OK,完全正确。 257 p=p->rchild; 258 } 259 } 260 } 261 262 //非递归后序遍历 263 void LastOrder(BiTree T,int i) 264 { 265 if(i==0) 266 printf("后序(非递归)遍历结果如下: "); 267 BiTree p=T,q=NULL; 268 SqStack s; 269 InitStack(s); 270 if(T) 271 { 272 while(1) 273 { 274 Push(s,p); 275 if(p->lchild) 276 p=p->lchild; 277 else 278 { 279 if(p->rchild) 280 p=p->rchild; 281 else 282 { 283 break; 284 } 285 } 286 }//while 287 while(1) 288 { 289 GetTop(s,p);//先获得栈顶指针,然后去判断 290 291 //若其右孩子已经被访问过,或是该元素没有右孩子,则由后序遍历的定义,此时可以visit这个结点了。 292 if(!p->rchild||s.visited) 293 { 294 Pop(s,q); 295 printf("%c",q->data); 296 } 297 else//右孩子存在,且未被访问 298 { 299 p=p->rchild; 300 while(p) 301 { 302 Push(s,p); 303 p=p->lchild; 304 } 305 s.visited=1; 306 } 307 if(s.length==0) 308 break; 309 }//while 310 } 311 } 312 313 int mainMenu() 314 { 315 system("cls"); 316 int choose; 317 char str[20]; 318 printf(" [1]构造二叉树 "); 319 printf(" [2]显示树状二叉树 "); 320 printf(" [3]遍历二叉树 ->>进入子菜单 "); 321 printf(" [4]查看二叉树信息 ->>进入子菜单 "); 322 printf(" [5]对二叉树进行操作 ->>进入子菜单 "); 323 printf(" [0]退出程序"); 324 printf(" *=*=*=*=*=*=*=**=*=*=**=*=*=**=*=*=**=*=*=*"); 325 printf(" 请输入你的选择: "); 326 while(1){ 327 scanf("%s",str);//接受输入 328 if(strcmp(str,"0")==0||strcmp(str,"1")==0||strcmp(str,"2")==0||strcmp(str,"3")==0 329 ||strcmp(str,"4")==0||strcmp(str,"5")==0){ 330 choose=atoi(str);//转化为整型 331 break; 332 } 333 else{printf(" 选择错误请重新输入: ");} 334 } 335 if(choose==0){printf(" …~~~…~~~谢谢使用本程序~~~…~~~… ");} 336 return choose; 337 } 338 int TraverseMenu() 339 { 340 system("cls"); 341 int choose; 342 char str[20]; 343 printf(" *=*=*=*=*=*=*=**=*=*=**=*=*=**=*=*=**=*=*=*"); 344 printf(" 请选择对应的选项按对应的方式遍历二叉树"); 345 printf(" *=*=*=*=*=*=*=**=*=*=**=*=*=**=*=*=**=*=*=*"); 346 printf(" [1]按先序(递归)遍历二叉树 "); 347 printf(" [2]按中序(递归)遍历二叉树 "); 348 printf(" [3]按后序(递归)遍历二叉树 "); 349 printf(" [4]按先序(非递归)遍历二叉树 "); 350 printf(" [5]按中序(非递归)遍历二叉树 "); 351 printf(" [6]按后序(非递归)遍历二叉树 "); 352 printf(" [7]按层次(非递归)遍历二叉树 "); 353 printf(" [0]返回主菜单"); 354 printf(" *=*=*=*=*=*=*=**=*=*=**=*=*=**=*=*=**=*=*=* "); 355 printf(" 请输入你的选择: "); 356 while(1){ 357 scanf("%s",str);//接受输入 358 if(strcmp(str,"0")==0||strcmp(str,"1")==0||strcmp(str,"2")==0||strcmp(str,"3")==0 359 ||strcmp(str,"4")==0||strcmp(str,"5")==0||strcmp(str,"6")==0||strcmp(str,"7")==0){ 360 choose=atoi(str);//转化为整型 361 break; 362 } 363 else{printf(" 选择错误请重新输入: ");} 364 } 365 if(choose==0){printf(" …~~~…~~~谢谢使用本程序~~~…~~~… ");} 366 return choose; 367 } 368 int main() 369 { 370 system("color e0"); 371 BiTree t; 372 int choose; 373 int flag=0; 374 while((choose=mainMenu())!=0) 375 { 376 switch(choose) 377 { 378 case 1: 379 if(flag==1) 380 printf("你已经创建树,请先销毁! "); 381 else 382 { 383 system("cls"); 384 CreateBiTree(t,0,0,'e'); 385 flag=1; 386 } 387 system("pause"); 388 break; 389 case 2: 390 if(flag!=1) 391 printf("你还没建树! "); 392 else 393 { 394 system("cls"); 395 int h; 396 h=TreeDepth(t,0,h); 397 printf("树的高度为:%d ",h); 398 printf("二叉树层序遍历结果为: "); 399 Lev_Traverse(t,h); 400 } 401 system("pause"); 402 break; 403 case 3: 404 if(!t) 405 printf("你还没建树! "); 406 else 407 { 408 while((choose=TraverseMenu())!=0) 409 { 410 switch(choose) 411 { 412 case 1:FirstPrint(t,0);printf(" "); 413 system("pause");break; 414 case 2:MiddlePrint(t,0);printf(" "); 415 system("pause");break; 416 case 3:LastPrint(t,0);printf(" "); 417 system("pause");break; 418 case 4:PreOrder(t,0);printf(" "); 419 system("pause");break; 420 case 5:InOrder(t,0);printf(" "); 421 system("pause");break; 422 case 6:LastOrder(t,0);printf(" "); 423 system("pause");break; 424 } 425 } 426 } 427 428 } 429 } 430 431 return 0; 432 }
线索二叉树(算法有点被绕到了)
#include<stdio.h> typedef enum PointerTag {Link,Thread};//Link=0,指针(指其左右孩子);Thread=1,线索(指前驱和后驱) typedef struct BiThrNode{ char data; struct BiThrNode *lchild,*rchild;//左右孩子指针 PointerTag LTag,RTag; }BiThrNode,*BiThrTree; BiThrTree pre; void InThreading(BiThrTree p) { if(p) { Inhreading(p->lchild);//左子树线索化 if(!p->lchild)//左子树为空 { p->LTag=Thread;//这个标记为线索 p->lchild=pre;//前驱线索 } if(!pre->rchild)//右子树为空 { pre->RTag=Thread; pre->rchild=p;//后继线索 } pre=p;//保持pre指向p的前驱。 Inhreading(p->lchild);//右子树线索化 } } void InOrderThreading(BiThrTree &Thrt,BiThrTree T) { if(!(Thrt=(BiThrTree)malloc(sizeof(BiThrNode)))) { printf("内存分配失败! "); exit(0); } Thrt->LTag=Link;//左标志为0,表示有左孩子 Thrt->RTag=Thread;//右标志位1,表示其后继 //建立头结点 Thrt->rchild=Thrt;//这是指它的后继 if(!T) Thrt->lchild=Thrt;//如果树为空,左指针也回指 else { Thrt->lchild=T;//这是指结点的前驱 pre=Thrt;//指向刚刚访问过的结点,为全局变量,Thrt能够改变也是因为它 InThreading(T); pre->rchild=Thrt; pre->RTag=Thread;//最后一个结点线索化 Thrt->rchild=pre; } } //中序遍历 void InOrderTraverse_Thr(BiThrTree T) { BiThrTree p; p=T->lchild; while(p!=T) { while(p->LTag==Link)//表明有左结点 { p=p->lchild; } printf("%c",p->data);//第一个左结点输出 while(p->RTag==Thread&&p->rchild!=T)//此时判断一下其后继 { p=p->rchild; printf("%c",p->data);//访问其后继 } p=p->rchild;//有右孩子 } }
赫夫曼编码
已经两次赫夫曼编码。。惭愧了
第一次的:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 typedef struct{ 5 unsigned int weight; 6 unsigned int parent,rchild,lchild; 7 }HTNode,*HuffmanTree;//动态分配数组存储赫夫曼树 8 typedef char **HuffmanCode;//动态分配数组存储赫夫曼编码表 9 10 void SelectNode(HuffmanTree &HT,int searchNodes,int &minIndex1,int &minIndex2) 11 { 12 minIndex1=minIndex2=0; 13 for(int i=0;i<searchNodes;i++) 14 { 15 if(HT[i].parent==0) 16 { 17 if((minIndex1==0)&&(minIndex2==0)) 18 { 19 minIndex1=i; 20 /* do 21 { 22 minIndex2=i+1; 23 } while(HT[minIndex2].parent!=0); 24 */ 25 minIndex2=i+1; 26 while(HT[minIndex2].parent!=0) 27 minIndex2++; 28 //保证1为最小 29 if(HT[i].weight>HT[i+1].weight) 30 { 31 HTNode temp={0,0,0,0}; 32 temp=HT[i]; 33 HT[i]=HT[i+1]; 34 HT[i+1]=temp; 35 int tempindex; 36 tempindex=minIndex1; 37 minIndex1=minIndex2; 38 minIndex2=tempindex; 39 } 40 } 41 42 else 43 { 44 if(HT[i].weight<HT[minIndex1].weight) 45 { 46 HTNode temp={0,0,0,0}; 47 temp=HT[minIndex1]; 48 HT[minIndex1]=HT[i]; 49 HT[minIndex2]=HT[minIndex1]; 50 minIndex1=i; 51 minIndex2=0; 52 } 53 if(HT[i].weight<HT[minIndex2].weight) 54 { 55 HT[minIndex2]=HT[i]; 56 minIndex2=i; 57 } 58 }//else 59 }//if 60 }//for 61 } 62 void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n){ 63 //w存放n个(叶子结点)字符的权值,构造赫夫曼树HT,并且求出n个字符的赫夫曼编码HC 64 if(n<=1) 65 return; 66 int m=2*n-1;//结点的总个数 67 HT=(HuffmanTree)malloc((m)*sizeof(HTNode));//书中提到0号单元未用,这是为什么呢?理解HT的定义,我先让它可用 68 HTNode *p; 69 int i,s1,s2; 70 for(p=HT,i=0;i<n;++i,++p,++w) 71 { 72 p->weight=*w; 73 p->parent=0; 74 p->lchild=0; 75 p->rchild=0; 76 printf("%d ",p->weight); 77 } 78 // *p={*w,0,0,0}; 79 for(;i<=m;++i,++p) 80 { 81 p->weight=0; 82 p->parent=0; 83 p->lchild=0; 84 p->rchild=0; 85 } 86 // *p={0,0,0,0}; 87 for(i=n;i<m;++i) 88 { //建赫夫曼树 89 //for(int k=m-1;k>=1;;k--) 90 /* for(int j=1;j<m;j++) 91 { 92 if(((HT[j].parent==0)&&(HT[j+1].parent==0))&&(HT[j].weight>HT[j+1].weight)) 93 s1=j+1; 94 } 95 for(int k=1;k<m;k++) 96 { 97 if(HT[k].weight >HT[s1].weight) 98 s2=k; 99 if(((HT[k].parent==0)&&(HT[k+1].parent==0))&&(HT[k].weight>HT[k+1].weight)) 100 s2=k+1; 101 }*/ 102 SelectNode(HT,i,s1,s2); 103 HT[s1].parent=i; 104 HT[s2].parent=i; 105 HT[i].lchild=s1; 106 HT[i].rchild=s2; 107 HT[i].weight=HT[s1].weight+HT[s2].weight; 108 } 109 //从叶子到根逆向求每个字符的赫夫曼编码 110 HC=(HuffmanCode)malloc((n+1)*sizeof(char *));//分配n个字符编码的头指针向量 111 char *cd; 112 char *mm; 113 int end,f; 114 unsigned int c; 115 cd=(char *)malloc(n*sizeof(char));//编码的最大空间 116 cd[n-1]='