数据结构
第一题 完全二叉树的判定
思路:
- 树的广度优先遍历实现,根节点先入队,然后出队
- 当p不为空时,不管p左右孩子是否为空,全部入队列
- 当p为空时,跳出循环,全部剩余节点出队列,如果后序存在非空节点,那么不是完全二叉树
代码:
typedef struct tnode{
int data;
struct tnode *left, *right;
}*tree;
bool iscompeltetree(tree root){
struct tnode *p =root;
tree queue[maxsize];
int front = -1, rear = -1;
queue[++rear] = root;
while(rear != front){
p = queue[++front];
if(p){
queue[++rear] = p->left;
queue[++rear] = p->right;
}
else{
break;
}
}
while(rear != front){
p = queue[++front];
if(p) return false;
}
return true;
}
第二题 深度优先遍历实现拓扑排序
若G是一个使用领接表存储的有向图,设计一个算法,利用深度优先遍历算法,对图中节点进行拓扑排序
思路:
- 深度优先遍历最深层的一个节点一定是拓扑序列的最后一个节点,然后依照深度优先遍历修改一下即可
代码:
typedef struct ArcNode{ //边结点
int adjvex;
struct ArcNode *next;
}ArcNode;
typedef struct VNode{ //顶点节点
int data;
struct ArcNode *firstarc;
}VNode;
typedef struct AGraph{ //领接表
VNode adjlist[maxsize];
int vexnum, edgenum;
}AGraph;
int visited[maxsize] = {0};
int topo[maxsize];
int t;
void dfs(AGraph *G, int v){
visited[v] = 1;
struct ArcNode *p = G->adjlist[v].firstarc;
while(p!=NULL){
if(visited[p->adjvex] == 0){
dfs(G,p->adjvex);
}
p =p->next;
}
topo[t--] = v; //深度最深的,是拓扑序列的最后一位,然后依次递减
}
void toposort(AGraph *G){
t = G->vexnum-1;
for(int i =0; i < G->vexnum; i++){
if(visited[i] == 0){
dfs(G,i);
}
}
}
程序设计
第一题 找到第k大整数 快排思想
1、假设包含m个元素的整型数组a,该数组存放了m个不重复的整数,编写函数求数组数组中第k大的整数,m>=1,1<=k<=m
思路:
- 快排思想,每次快排都可以找到一个数的大小位置,所以在经过每次划分后,对loc中间节点与m-k进行比较,如果loc>m-k,则在左半边进行查找,如果loc<m-k,则在右半边进行查找
代码:
//快速排序的思想,每次交换后i,j指针将数组划分为两部分,左边是小于low的,右边是大于low的
int quicksort(int a[], int m, int k){
int low = 0, high = m-1;
while(low < high){
int i = low, j = high+1;
int pivot = a[low];
while(i < j){
i++;
while(a[i] <= pivot) i++;
j--;
while(a[j] > pivot) j--;
if(i < j){
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
int temp = a[j];
a[j] = a[low];
a[low] = temp;
if(j == m-k){
break;
}
else if(j > m-k){
high = j-1;
}
else{
low = j+1;
}
}
printf("第%d大的数为:%d",k,a[m-k]);
return a[m-k];
}
第二题 数组的二进制加1
2、假设用整型数组存储二进制数,即数组的一个元素存放二进制数的一位,编写函数实现该存储形式的二进制数的加1运算
思路:
- 添加一个参数保存进位
- 同时还需要判断最后位数需要加1,需要的话,整体后移
代码:
//思路:先不断加1,然后判断最后一位是否需要加1
void binaryarray(int a[], int n){
int carry = 1;
for(int i = n-1; i >=0; i--){
int temp = a[i]+carry;
a[i] = temp%2;
carry = temp/2;
}
if(carry){
for(int i = n-1; i >=0; i--){
a[i+1] = a[i];
}
a[0] = carry;
}
}
第三题 机器人对话
现在有两个机器人对话M1,M2要进行对话,规则如下
M1只会说"Y",“N”,“2”
M2只会说"y",“n”,“1”
M1主动说话
当一个机器人说的不是数字时,他自己必须继续说话,对方不能说话
当一个机器人说出数字时,自己停止说话,对方接着说话,也可以不说话从而结束对话
编写程序判断输出的任意非空字符串是否是两个机器人对话终止时的形成的串
思路:
- 按照题意模拟即可
- 先判断开头是否是机器人M1说话,不是直接返回fasle
- 是的话,继续判断是否是M1和M2轮流说话,中间的标志就是M2与M1之间的对话之间一定得有1或者2进行轮换,如果没有,则不是机器人对话,直接break
代码:
bool isrobot1(char s){
if(s == 'Y' || s == 'N' || s=='2'){
return true;
}
else return false;
}
bool isrobot2(char s){
if(s == 'y' || s == 'n' || s=='1'){
return true;
}
else return false;
}
bool iscommuncate(char *s1){
int i = 0;
if(!isrobot1(s1[i++])) return false; //第一个不是机器人M1说话
while(s1[i] != '\0'){
while(isrobot1(s1[i]) && s1[i] != '2'){ //是机器人M1说话,并且不结束
i++; //继续说话
}
if(s1[i++]!='2') break; //如果M1还没结束,M2就说话, 不符合规则
while(isrobot2(s1[i]) && s1[i] != '1'){ //是机器人M2说话,并且不结束
i++; //继续说话
}
if(s1[i++]!='1') break; //如果M2还没结束,M1就说话, 不符合规则
}
if(s1[i] != '\0') return false; //不是机器人之间的对话
else return true; //是机器人之间的对话
}