数据结构
第一题
1、领接表结构判断u与v之间有无路径
思路: 深度优先遍历或者广度优先遍历
typedef struct ArcNode{ //领接边
int adjvex;
struct ArcNode *next;
}ArcNode;
typedef struct VNode{ //顶点
int data;
ArcNode *firstarc;
}VNode;
typedef struct{ //领接表
VNode adjlist[maxsize];
int vexnum, edgenum;
}AGraph;
//采用广度优先遍历
bool isroad(AGraph *G, int u, int v){
int visited[G->vexnum];
ArcNode *p; //工作指针
int queue[maxsize]; //队列
int i,k,front=-1,rear=-1;
for(i=0; i < G->vexnum; i++){ //初始化visited数组
visited[i] = 0;
}
queue[++rear] = u;
visited[u] = 1; //节点入队列
while(rear != front){ //层次遍历
k = queue[++front]; //出队
p = G->adjlist[k].firstarc;
while(p!=NULL){ //层次遍历该节点的领接点
if(visited[p->adjvex]==0){ //未被访问,入队,访问
if(p->adjvex == v){ //如果存在回路,直接返回true
return true;
}
visited[p->adjvex] = 1;
queue[++rear] = p->adjvex;
}
p = p->next;
}
}
return false;
}
第二题
2、链表的合并,将两个链表合并为一个升序链表(尾插法)(降序:头插法)
思路: 申请一个带头结点的链表进行插入,考虑两个节点数值相等的情况下需要两个指针一起移动
typedef struct node{
int data;
struct node *next;
}*list;
list merge(list head1, list head2){//默认不带头结点
struct node *newhead = (struct node *)malloc(sizeof(struct node));
struct node *p1 = head1, *p2 = head2,*p = newhead;
while(p1 != NULL && p2 != NULL){//合并两个链表
if(p1->data > p2->data){ //p1大于p2
p->next = p2;
p = p->next;
p2 = p2->next;
}
else if(p1->data < p2->data){//p2大于p1
p->next = p1;
p = p->next;
p1 = p1->next;
}
else{ //p1等于p2
p->next = p1;
p = p->next;
p1 = p1->next;
p2 = p2->next;
}
}
if(p1!=NULL){ //处理剩余节点
p->next = p1;
}
else{
p->next = p2;
}
p = newhead->next;
while(p!=NULL){
printf("%5d",p->data);
p = p->next;
}
return newhead->next; //返回不带头结点的单链表
}
程序设计
第一题
1、计算数组的最大的滑动窗口数,最大连续子集的元素个数
思路:
动态规划,如果前面的值不为负数,那么加上当前的数肯定是要大
if dp[i-1]>0 dp[i] = dp[i-1] + a[i]
else dp[i]=a[i]
然后考虑是否比当前的最大值要大,更大的话,进行更新
int maxnum(int a[], int n){
int tail, head,i,max=0;
int dp[n]; //为当前以a[i]为结尾的最大连续元素和的最大值
dp[0] = a[0];
for(i=1; i < n; i++){
if(dp[i-1] < 0){ //如果前一个最大值为负数,直接舍弃
dp[i] = a[i];
head = i;
}
else{ //如果是正数就一直加
dp[i] = dp[i-1] + a[i];
}
if(dp[i] > max){ //超过了当前最大值,进行更新
tail = i;
max = dp[i];
}
}
printf("最大滑动窗口数为%d, 起始下标%d, 终止下标%d",tail-head+1, head, tail);
return tail-head+1;
}
第二题
2、删除链表里面的重复节点,带头结点
思路: 双重for循环比较,需要两个指针一个是工作节点,一个是当前节点的前驱节点(这里采用带头结点的链表)
list deletesame(list head){
struct node *p=head->next, *pre=head, *q;
while(p!=NULL){
q = p->next;
while(q!=NULL){
if(p->data == q->data){//元素相同,则进行删除p节点
pre->next = p->next;
free(p);
p = pre->next;
}
q = q->next;
}
pre = p; //继续往下找
p = p->next;
}
p = head->next;
while(p!=NULL){
printf("%-5d",p->data);
p = p->next;
}
}
第三题
3、递归判断一个二叉树是否对称
思路:
递归实现:
- 左右节点均为空,返回true
- 左右节点有一个为空,返回false
- 左右节点不为空且左右节点不相等 返回 false
- 左右节点不为空且左右节点相等 递归判断左右子树
typedef struct tnode{
int data;
struct tnode *left, *right;
}*tree;
bool symmetry(tree p, tree q){
if(p==NULL && q==NULL) return true; //左右子树都空,对称
else if(p==NULL|| q==NULL) return false; //左右子树有一个不为空,不对称
else if(p->data != q->data) return false; //左右节点不相等,不对称
else //左右子树节点不为空且相等,递归判断
return symmetry(p->left,q->right)&&symmetry(p->right,q->left);
}
bool judge(tree root){
if(root==NULL) return true;
return symmetry(root->left, root->right);
}