二叉排序树的判定
【问题描述】课后作业第6题。试写一个判别给定二叉树是否为二叉排序树的算法。以前序遍历序列和中序遍历序列给出该二叉树的结点,并创建该二叉树。然后再进行判断。请注意,树中结点关键字可能相同。
【样例输入1】
6 4 5 8 6 9 0
4 5 6 6 8 9 0
【样例输出1】
true
【样例输入2】
6 4 7 8 0
4 7 6 8 0
【样例输出2】
false
【提示】若直接根据给定的中序是否有序来进行判断,此种判断方法不得分。务必先创建二叉树的链式存储,再对其进行判断。
#include<iostream>
#include<stdlib.h>
#define N 50
using namespace std;
typedef struct Node
{
int data;
struct Node * LChild;
struct Node * RChild;
}BtNode, * BiTree;
BiTree root = NULL;
bool res = true;
int r[N];
int count = 0;
void CreatBiTree(BiTree * root, int PreOrder[20], int InOrder[20], int PreLeft, int PreRight, int InLeft, int InRight)
{
if(InLeft > InRight) *root = NULL;
else
{
*root = (BtNode*)malloc(sizeof(BtNode));
(*root)->data = PreOrder[PreLeft];
int i = 0;
int mid = 0;
for(i = InRight; i >= InLeft; i --)
{
if(InOrder[i] == PreOrder[PreLeft])
{
int j, k;
bool flag = true;
for(j = PreLeft + i - InLeft; j > PreLeft; j --)
{
for(k = InLeft; k < i; k ++)
{
if(PreOrder[j] == InOrder[k]) break;
}
if(k == i)
{
flag = false;
break;
}
}
if(flag)
{
mid = i;
break;
}
else continue;
}
}
for(i = mid - 1; i >= InLeft; i --)
{
if(InOrder[i] == InOrder[mid])
{
res = false;
break;
}
}
CreatBiTree(&((*root)->LChild), PreOrder, InOrder, PreLeft + 1, PreLeft + mid - InLeft, InLeft, mid - 1);
CreatBiTree(&((*root)->RChild), PreOrder, InOrder, PreLeft + mid - InLeft + 1, PreRight, mid + 1, InRight);
}
}
void Order(BtNode * ptr)
{
if(ptr == NULL)
return ;
else
{
Order(ptr->LChild);
r[count ++] = ptr->data;
Order(ptr->RChild);
}
}
int main()
{
int PreOrder[20];
int InOrder[20];
int cnt = 0;
int i = 0;
for(i = 0; ; i ++)
{
cin>>PreOrder[i];
if(PreOrder[i] == 0) break;
cnt ++; // cnt维数组下标的最后一位
}
for(i = 0; ; i ++)
{
cin>>InOrder[i];
if(InOrder[i] == 0) break;
}
CreatBiTree(&root, PreOrder, InOrder, 0, cnt - 1, 0, cnt - 1);
if(!res) cout<<"false"<<endl;
else
{
Order(root);
for(i = 0; i < count; i ++)
{
if(r[i] < r[i-1])
{
break;
}
}
if(i < count ) cout<<"false";
else cout<<"true";
}
return 0;
}
二叉排序树
【问题描述】
请根据输入的数据创建一棵二叉排序树。然后执行相应操作。
1 删除某一值为x的结点
2 求指定结点y在二叉排序树中的层数
【输入形式】
结点数据,以0代表结束输入。
待删除的x,待求层数的y
【输出形式】
创建好的二叉排序树的拓展的前序遍历结果
删除后的二叉排序树的中序遍历结果
y所在的层数
【样例输入】
29 39 15 25 28 10 11 2 0
10
11
【样例输出】
29 15 10 2 # # 11 # # 25 # 28 # # 39 # #
2 11 15 25 28 29 39
4
【样例说明】
若待删除的结点包含左右子树,则以其左子树的最右结点代替它。
#include<iostream>
#include<stdlib.h>
using namespace std;
typedef struct node
{
int data;
struct node * LChild;
struct node * RChild;
}SortTreeNode, *SortTree;
SortTreeNode * root;
void Insert(int num)
{
SortTreeNode * ptr = root;
SortTreeNode * pre = NULL;
while(ptr != NULL)
{
if(num < ptr->data)
{
pre = ptr;
ptr = ptr->LChild;
}
else
{
pre = ptr;
ptr = ptr->RChild;
}
}
SortTreeNode * temp = (SortTree)malloc(sizeof(SortTreeNode));
temp->data = num;
temp->LChild = NULL;
temp->RChild = NULL;
if(temp->data < pre->data)
{
pre->LChild = temp;
}
else
{
pre->RChild = temp;
}
}
void Creat()
{
int num = 0;
cin>>num;
root = new SortTreeNode; //new后加空间类型
root->data = num;
root->LChild = NULL;
root->RChild = NULL;
while(1)
{
cin>>num;
if(num == 0)
break;
Insert(num); //插入节点前先保证root有数值可比较
}
}
void PreOrder(SortTreeNode * r)
{
if(r != NULL)
{
cout<<r->data<<" ";
PreOrder(r->LChild);
PreOrder(r->RChild);
}
else
{
cout<<"#"<<" ";
}
return ;
}
void Delet()
{
int num;
cin>>num;
SortTreeNode * ptr = root;
SortTreeNode * pre = NULL;
while(ptr->data != num && ptr != NULL)
{
if(num < ptr->data)
{
pre = ptr;
ptr = ptr->LChild;
}
else
{
pre = ptr;
ptr = ptr->RChild;
}
}
if(ptr->LChild == NULL)
{
if(ptr->RChild == NULL)
{
if(ptr->data < pre->data)
pre->LChild = NULL;
else
pre->RChild = NULL;
}
else
{
if(pre == NULL)
{
root = root->RChild;
}
else
{
if(ptr->data < pre->data)
pre->LChild = ptr->RChild;
else
pre->RChild = ptr->RChild;
}
}
}
else if(ptr->RChild == NULL)
{
if(pre == NULL)
{
root = root->LChild;
}
else
{
if(ptr->data < pre->data)
pre->LChild = ptr->LChild;
else
pre->RChild = ptr->LChild;
}
}
else
{
if(pre == NULL) //要删除的节点就是根
{
SortTreeNode * temp = ptr->LChild;
SortTreeNode * pretemp = ptr;
while(1)
{
if(temp->RChild == NULL)
break;
pretemp = temp;
temp = temp->RChild;
} //temp指向删除节点左子树的最大节点,pretemp指向temp的前驱
if(pretemp == ptr) //最大节点就是它的左孩子
{
temp->RChild = root->RChild;
root = temp;
}
else
{
pretemp->RChild = temp->LChild;
temp->LChild = root->LChild;
temp->RChild = root->RChild;
root = temp;
}
}
else //要删除的节点不是根节点
{
SortTreeNode * temp = ptr->LChild;
SortTreeNode * pretemp = ptr;
while(1)
{
if(temp->RChild == NULL)
break;
pretemp = temp;
temp = temp->RChild;
} //temp指向删除节点左子树的最大节点,pretemp指向temp的前驱
if(pretemp == ptr) //最大节点就是它的左孩子
{
temp->RChild = ptr->RChild;
if(pre->LChild == ptr)
pre->LChild = temp;
else
pre->RChild = temp;
}
else
{
pretemp->RChild = temp->LChild;
temp->LChild = ptr->LChild;
temp->RChild = ptr->RChild;
if(pre->LChild == ptr)
pre->LChild = temp;
else
pre->RChild = temp;
}
}
}
}
void InOrder(SortTreeNode * r)
{
if(r != NULL)
{
InOrder(r->LChild);
cout<<r->data<<" ";
InOrder(r->RChild);
}
return ;
}
void FindLevel()
{
int num;
cin>>num;
SortTreeNode * temp = root;
int cnt = 1;
while(temp->data != num)
{
if(num < temp->data)
{
temp = temp->LChild;
cnt ++;
}
else
{
temp = temp->RChild;
cnt ++;
}
}
cout<<cnt;
}
int main()
{
Creat();
PreOrder(root);
cout<<endl;
Delet();
InOrder(root);
cout<<endl;
FindLevel();
return 0;
}
二叉查找树的后序遍历
【问题描述】输入一个整数数组,判断该数组是不是某二叉查找树的后序遍历的结果。如果是返回true,否则返回false。
【输入形式】输入任意长度的数组,数字之间空格分开
【输出形式】true 或者 false
【样例输入】输入5 7 6 9 11 10 8
【样例输出】true
【样例说明】由于这一整数序列是如下树的后序遍历结果:
8
/ \
6 10
/ \ / \
5 7 9 11
因此返回true。
【评分标准】暴力求解法不得分。
【提示】后序遍历的最后一个结点一定是根结点,那么前面的数据就可以划分为比根小的、比根大的。依此类推下去。
#include<iostream>
#include<stdlib.h>
using namespace std;
typedef struct node
{
int data;
struct node * LChild;
struct node * RChild;
}SortTreeNode, * SortTree;
SortTree root;
int a[20];
int res[20];
int cnt = 0;
void Insert(int node)
{
SortTreeNode * ptr = root;
SortTreeNode * pre = NULL;
while(ptr != NULL)
{
if(a[node] < ptr->data)
{
pre = ptr;
ptr = ptr->LChild;
}
else
{
pre = ptr;
ptr = ptr->RChild;
}
}
SortTreeNode * temp = (SortTree)malloc(sizeof(SortTreeNode));
temp->data = a[node];
temp->LChild = NULL;
temp->RChild = NULL;
if(temp->data < pre->data)
{
pre->LChild = temp;
}
else
{
pre->RChild = temp;
}
}
void Creat(int limit)
{
int i = limit - 1;
root = (SortTree)malloc(sizeof(SortTreeNode));
root->data = a[i];
root->LChild = NULL;
root->RChild = NULL;
i --;
while(i >= 0)
{
Insert(i);
i --;
}
}
void PostOrder(SortTreeNode * r)
{
if(r != NULL)
{
PostOrder(r->LChild);
PostOrder(r->RChild);
res[cnt ++] = r->data;
}
return ;
}
int main()
{
int i = 0;
while(cin>>a[i])
{
i ++;
}
Creat(i); //i取不到
PostOrder(root);
for(i = 0; i < cnt; i ++)
{
if(res[i] != a[i])
{
break;
}
}
if(i == cnt) cout<<"true";
else cout<<"false";
}
八数码问题(哈希查找)
【问题描述】
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局,找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
【输入形式】
输入初始状态,一行九个数字,空格用0表示
【输出形式】
只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)
【样例输入】
2 6 4 1 3 7 0 5 8
8 1 5 7 3 6 4 0 2
【样例输出】
31
【说明】
虽然有很多种解法,但本次作业必须采用到哈希查找技术
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
const int M=10000000;
const int N=100010,P=13331;
ULL h[N];
int d[M];
ULL hash_CSM(string a)
{
h[0]=0;
for(int i=1;i<=9;i++)
{
h[i]=h[i-1]*P+(a[i-1]-'0'+1);
}
return h[9]%M;
}
int bfs(string state, string end)
{
queue<string>q;
q.push(state);
d[hash_CSM(state)]=0;
int dx[4]={0,0,-1,1};
int dy[4]={1,-1,0,0};
while(q.size())
{
string t=q.front();
q.pop();
if(t==end)return d[hash_CSM(t)];
int distance=d[hash_CSM(t)];
int k=t.find('0');
int x=k/3,y=k%3;
for(int i=0;i<4;i++)
{
int a=x+dx[i];
int b=y+dy[i];
if(a>=0&&a<3&&b>=0&&b<3)
{
swap(t[a*3+b],t[k]);
if(!d[hash_CSM(t)])
{
d[hash_CSM(t)]=distance+1;
q.push(t);
}
swap(t[a*3+b],t[k]);
}
}
}
return -1;
}
int main()
{
string state;
string end;
char c;
for(int i=0;i<9;i++)
{
cin>>c;
state+=c;
}
for(int i=0;i<9;i++)
{
cin>>c;
end+=c;
}
cout << bfs(state, end) << endl;
return 0;
}
世界上有2片相同的雪花吗
【题目来源】3349 – Snowflake Snow Snowflakes (poj.org)
Description
You may have heard that no two snowflakes are alike. Your task is to write a program to determine whether this is really true. Your program will read information about a collection of snowflakes, and search for a pair that may be identical. Each snowflake has six arms. For each snowflake, your program will be provided with a measurement of the length of each of the six arms. Any pair of snowflakes which have the same lengths of corresponding arms should be flagged by your program as possibly identical.
Input
The first line of input will contain a single integer n, 0 < n ≤ 100000, the number of snowflakes to follow. This will be followed by n lines, each describing a snowflake. Each snowflake will be described by a line containing six integers (each integer is at least 0 and less than 10000000), the lengths of the arms of the snow ake. The lengths of the arms will be given in order around the snowflake (either clockwise or counterclockwise), but they may begin with any of the six arms. For example, the same snowflake could be described as 1 2 3 4 5 6 or 4 3 2 1 6 5.
Output
If all of the snowflakes are distinct, your program should print the message:
No two snowflakes are alike.
If there is a pair of possibly identical snow akes, your program should print the message:
Twin snowflakes found.
Sample Input
2
1 2 3 4 5 6
4 3 2 1 6 5
Sample Output
Twin snowflakes found.
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int HASH=99991;
const int MAXN=100000+5;
typedef int snow[6];
snow st[MAXN];
int head[HASH],next[MAXN];
int hash(snow& s)
{
int i,v=0;
for(i=0;i<6;i++)
v=v+s[i];
return v%HASH;
}
bool compare(snow& s,snow& t)
{
int i;
for(i=0;i<6;i++)
if((s[i%6]==t[0]&&
s[(i+1)%6]==t[1]&&
s[(i+2)%6]==t[2]&&
s[(i+3)%6]==t[3]&&
s[(i+4)%6]==t[4]&&
s[(i+5)%6]==t[5])||
(s[i%6]==t[5]&&
s[(i+1)%6]==t[4]&&
s[(i+2)%6]==t[3]&&
s[(i+3)%6]==t[2]&&
s[(i+4)%6]==t[1]&&
s[(i+5)%6]==t[0]))
return true;
return false;
}
bool search(int r)
{
int h=hash(st[r]);
int u=head[h];
while(u)
{
if(compare(st[u],st[r])) return true;
u=next[u];
}
next[r]=head[h];
head[h]=r;
return false;
}
int main()
{
int n,i,k=1;
memset(head,0,sizeof(head));
memset(next,0,sizeof(next));
cin>>n;
while(n--)
{
for(i=0;i<6;i++)
cin>>st[k][i];
if(search(k)) { cout<<"Twin snowflakes found."; return 0;}
k++;
}
cout<<"No two snowflakes are alike.";
return 0;
}