一、数组实现二叉树(下标从0开始)
#include <stdio.h>
typedef struct _TreeNode{
int data;
bool IsEmpty; //结点是否为空 // 因为我们的二叉树不一定是满二叉树,中间可能有一些节点不存在 // 值为1代表空
}TreeNode;
// 初始化
void InitTreeNode(TreeNode t[],int len){
for(int i=0;i<len;i++)
t[i].IsEmpty = 1;
}
bool IsEmpty(TreeNode t[],int len,int idx){
if(idx >= len || idx < 0) return 1; // 修改为0
return t[idx].IsEmpty;
}
// father = (child-1)/2 or father = child/2 - 1
int findFather(TreeNode t[],int len,int idx){
if(idx == 0) return -1; //特判根节点没有父节点 // 特判也修改为0
int fatheridx = (idx-1) / 2;
if(IsEmpty(t,len,fatheridx)) return -1;
return fatheridx;
}
// lchild = father*2 + 1
int findLchild(TreeNode t[],int len,int idx){
int lchild = idx*2 + 1;
if(IsEmpty(t,len,lchild)) return -1;
return lchild;
}
// rchild = father*2+2
int findRchild(TreeNode t[],int len,int idx){
int rchild = idx*2 + 2;
if(IsEmpty(t,len,rchild)) return -1;
return rchild;
}
//实现前序遍历, 从下表为idx的节点开始前序遍历
int PreorderTree(TreeNode t[],int len,int idx){
if(IsEmpty(t,len,idx)) return 0;
printf("%d\n",t[idx].data);
PreorderTree(t,len,findLchild(t,len,idx));
PreorderTree(t,len,findRchild(t,len,idx));
return 0;
}
int InorderTree(TreeNode t[],int len,int idx){
if(IsEmpty(t,len,idx)) return 0;
InorderTree(t,len,findLchild(t,len,idx));
printf("%d\n",t[idx].data);
InorderTree(t,len,findRchild(t,len,idx));
return 0;
}
int PostorderTree(TreeNode t[],int len,int idx){
if(IsEmpty(t,len,idx)) return 0;
PostorderTree(t,len,findLchild(t,len,idx));
PostorderTree(t,len,findRchild(t,len,idx));
printf("%d\n",t[idx].data);
return 0;
}
int main(){
TreeNode Td[100]; // 这里的二叉树节点要从0开始
int fatheridx;
int testLen = 7; // IsEmpty 的判断是 >=Len 所以这里加一个1
for(int i=0;i<=testLen;i++){
Td[i].data = i+1;
Td[i].IsEmpty = 0;
}
PreorderTree(Td,testLen,0);
// InorderTree(Td,testLen,0);
// PostorderTree(Td,testLen,0);
return 0;
}
二、数组实现二叉树(下标从1开始)
#include <stdio.h>
typedef struct _TreeNode{
int data;
bool IsEmpty; //结点是否为空 // 因为我们的二叉树不一定是满二叉树,中间可能有一些节点不存在 // 值为1代表空
}TreeNode;
// 初始化
void InitTreeNode(TreeNode t[],int len){
for(int i=0;i<len;i++)
t[i].IsEmpty = 1;
}
bool IsEmpty(TreeNode t[],int len,int idx){
if(idx >= len || idx < 1) return 1;
return t[idx].IsEmpty;
}
// father = child / 2
int findFather(TreeNode t[],int len,int idx){
// if(idx == 1) return -1; //特判根节点没有父节点 ,不加也没事,但下表从0开始的时候必须加
int fatheridx = idx / 2;
if(IsEmpty(t,len,fatheridx)) return -1;
return fatheridx;
}
// lchild = father*2
int findLchild(TreeNode t[],int len,int idx){
int lchild = idx*2;
if(IsEmpty(t,len,lchild)) return -1;
return lchild;
}
// rchild = father*2+1
int findRchild(TreeNode t[],int len,int idx){
int rchild = idx*2+1;
if(IsEmpty(t,len,rchild)) return -1;
return rchild;
}
//实现前序遍历, 从下表为idx的节点开始前序遍历
int PreorderTree(TreeNode t[],int len,int idx){
if(IsEmpty(t,len,idx)) return 0;
printf("%d\n",t[idx].data);
PreorderTree(t,len,findLchild(t,len,idx));
PreorderTree(t,len,findRchild(t,len,idx));
return 0;
}
int InorderTree(TreeNode t[],int len,int idx){
if(IsEmpty(t,len,idx)) return 0;
InorderTree(t,len,findLchild(t,len,idx));
printf("%d\n",t[idx].data);
InorderTree(t,len,findRchild(t,len,idx));
return 0;
}
int PostorderTree(TreeNode t[],int len,int idx){
if(IsEmpty(t,len,idx)) return 0;
PostorderTree(t,len,findLchild(t,len,idx));
PostorderTree(t,len,findRchild(t,len,idx));
printf("%d\n",t[idx].data);
return 0;
}
int main(){
TreeNode Td[100]; // 这里的二叉树节点要从一开始
int fatheridx;
int testLen = 7+1; // IsEmpty 的判断是 >=Len 所以这里加一个1
for(int i=1;i<=testLen;i++){
Td[i].data = i;
Td[i].IsEmpty = 0;
}
PreorderTree(Td,testLen,1);
// InorderTree(Td,testLen,1);
// PostorderTree(Td,testLen,1);
return 0;
}
三、并查集及其优化思路
#include <stdio.h>
#define MAXSIZE 50
int UFSets[MAXSIZE];
void InitUFSets(int S[]){
for(int i=0;i<MAXSIZE;i++){
S[i] = -1;
}
}
int find(int S[],int x){
if(S[x] == -1) return x; // -1说明到底了
return find(S,S[x]);
}
int pathCompFind(int S[],int x){ // 路径压缩策略优化Find 操作
if(S[x] >= 0){
S[x] = find(S,S[x]);
return S[x];
}
return x;
}
bool UnionElem(int S[],int elem1,int elem2){ //王道书上是直接合并的root,而不是元素成员
int first = find(S,elem1);
int second = find(S,elem2);
if(first != second){
printf("%d -- %d\n",first,second);
S[second] = first;
return 1;
}
return 0;
}
bool UnionRoot(int S[],int Root1,int Root2){
if(Root1 == Root2) return 0; //比较两个根是否来自同一集合
S[Root2] = Root1; // 将根Root2连接到Root1上
return 1;
}
bool optUnionRoot(int S[],int Root1,int Root2){
if(Root1 == Root2) return 0;
if(S[Root2] > S[Root1]){ // Root2 结点数更少 // 因为初始化的时候S的值全为 -1 所以 若S[Root1]与S[Root2]相加后为更小的负数
//较小的树,树较大,这也是为什么 S[Root1] >= S[Root2]时 却把Root2合并到Root1中的原因
S[Root1] += S[Root2]; // 累加节点个数
S[Root2] = Root1;
}else{
S[Root2] += S[Root1];
S[Root1] = Root2;
}
return 1;
}
void debug(){
for(int i=0;i<MAXSIZE;i++){
printf("%d ",UFSets[i]);
}
puts("");
}
int main(){
InitUFSets(UFSets);
int arr[100] = {0,1,2,3,4,5,6,7,8,9};
for(int i=0;i<=10;i++){
UnionElem(UFSets,arr[i*2],arr[i*2+1]);
// 0 -- 1
// 2 -- 3
// 4 -- 5
// 6 -- 7
// 8 -- 9
}
UnionElem(UFSets,1,3);
UnionElem(UFSets,5,7);
// 0 -- 1
// 2 -- 3
// 4 -- 5
// 6 -- 7
// 8 -- 9
// 0 -- 2
// 4 -- 6
UnionElem(UFSets,1,6);
UnionElem(UFSets,2,7);
// debug();
return 0;
}