20/1/20树的遍历、进制转换
树的遍历
树的遍历方式有三种,分别是前序、中序以及后序遍历。前、中、后说明的是根节点出现的位置,即前序遍历指先根,再左子树最后右子树。
要想利用程序实现树的遍历,首先应选取恰当的数据结构,树形结构多数构造结构体,利用指针存储。如下:
数据结构选择
struct Node{
int data;
Node* lchild;
Node* rchild;
};
树的创建
这里以二叉搜索树的创建为例。
二叉搜索树:任一结点的左子树仅包含严格小于该结点的键值,而其右子树包含大于或等于该结点的键值。
Node* butree(Node* Btree,int x){//树的生成
if(!Btree){//树为空
Btree=(Node*)malloc(sizeof(struct Node));//不可省略
Btree->data=x;
Btree->lchild=NULL;
Btree->rchild=NULL;
if(x<Btree->data){
Btree->lchild=butree(Btree->lchild,x);
}else if(x>=Btree->data){
Btree->rchild=butree(Btree->rchild,x);
}
}
return Btree;
}
创建好合适的树形结构之后,也就有了遍历的基础。
遍历的方式有递归和迭代两种方式,递归方式代码简洁,逻辑结构也相当清晰,但内存消耗较大。相比之下,迭代的实现方式更注重过程的思想,利用栈来实现三种遍历。
递归实现树的遍历
void po(Node* root){//先序遍历
if(root){
a1[num1++]=root->data;
po(root->lchild);
po(root->rchild);
}
}
中序以及后序遍历与前序遍历的思想相同,只需修改获取结点值的语句的位置即可。(上文第三行代码)
迭代实现树的遍历
明日补充
进制转换
十六进制转八进制
十六进制的每一位数字对应四位二进制数字;八进制的每一位数字对应三位二进制数字,高位不足补零。
故:十六进制转八进制数,可依照如下思路完成
- 将十六进制数字按位转化为4位二进制数,存入数组/字符串~~(字符串较为好用一些,因为字符串的合并通过+便可实现)~~
- 统计形成的二进制数的位数是否是3的整数倍,若不是则在左侧添0
- 从左到右依次扫描二进制数组( 字符串),每三位计算一次结果并输出。
实现全代码如下:
#include<bits/stdc++.h>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<string.h>
#define ll long long
#define INF 10000
#include<map>
#include<stack>
#include<queue>
#include<stdio.h>
#include<string.h>
using namespace std;
int A[4000005];
int ans[2000005];
int main(){
int N;
scanf("%d",&N);
int num=0;
while(N--){
char s[100005];
string s1="";
cin>>s;
int len=strlen(s);
//cout<<len<<" "<<4*len<<endl;
for(int i=0;i<len;i++){
//cout<<s[i]<<" ";
switch(s[i]){
case '0':
s1+="0000";break;
case '1':
s1+="0001";break;
case '2':
s1+="0010";break;
case '3':
s1+="0011";break;
case'4':
s1+="0100";break;
case '5':
s1+="0101";break;
case '6':
s1+="0110";break;
case'7':
s1+="0111";break;
case '8':
s1+="1000";break;
case '9':
s1+="1001";break;
case'A':
s1+="1010";break;
case 'B':
s1+="1011";break;
case 'C':
s1+="1100";break;
case'D':
s1+="1101";break;
case 'E':
s1+="1110";break;
case 'F':
s1+="1111";break;
}
}
int le=s1.length();
if(le%3==1){//位数不足,则补0
s1="00"+s1;
le+=2;
}else if(le%3==2){
s1="0"+s1;
le+=1;
}
// cout<<s1<<" "<<le<<endl;
for(int i=0;i<le;){
int t=0;
for(int j=0;j<3;j++){
t+=(s1[i+j]-'0')*pow(2,2-j);
}
ans[num++]=t;
i+=3;
}
int flag=1;
for(int i=0;i<num;i++){
if(flag&&ans[i]!=0){
flag=0;
}
if(flag) continue;
cout<<ans[i];
}
cout<<endl;
num=0;
}
return 0;
}
十进制转其他进制
无需借助额外的进制,循环除再倒着输出就可以了,代码如下:
void zhuan(int n){//十进制转八进制
int num=0;
while(n){
A[num++]=n%8;
n/=8;
}
}
输出时逆序输出就可以了。如果是字符串来保存数组,可以利用reverse(A,A+num)来逆转字符数组。
转为十六进制时由于会出现二位数,可选择利用字符串来保存结果。