题目24分析:(反转链表)
反转单向链表,为防止链表断裂,需定义三个指针,分别指向当前遍历节点、上一个遍历节点、下一个遍历节点遍历节点直至尾节点,首先令当前节点指向上一个节点,然后令上一个节点为当前节点,当前节点为下一个结点
思路:
1.初始化反转后链表的头节点=NULL,当前节点是头节点,上一个节点=NULL
2.遍历当前节点,直至为空
3.更新当前节点的下一个结点,如果下一个结点为空时,则获得反转链表的头节点
4.令当前节点指向上一个节点
5.令上一个节点为当前节点,当前节点为下一个结点
#include <iostream> using namespace std; struct LinkNode { int data; LinkNode *next; }; //创建链表 void create_link(LinkNode *head_ptr, int length) { for (int i = length; i >= 1; --i) { LinkNode *new_node = new LinkNode; new_node->data = i; new_node->next = head_ptr->next; head_ptr->next = new_node; } } //打印链表内容 void print_link(LinkNode *head_ptr, int length) { LinkNode *temp_node = head_ptr->next; while (temp_node != NULL) { cout << temp_node->data << " "; temp_node = temp_node->next; } cout << endl; } LinkNode* reverse_link(LinkNode *head_ptr) { //1.初始化反转后链表的头节点=NULL,当前节点是头节点,上一个节点=NULL LinkNode *reverse_head_node = NULL; LinkNode *cur_node = head_ptr->next; LinkNode *last_node = NULL; //2.遍历当前节点,直至为空 while (cur_node != NULL) { //3.更新当前节点的下一个结点,如果下一个结点为空时,则获得反转链表的头节点 LinkNode *next_node = cur_node->next; if (next_node == NULL) reverse_head_node = cur_node; //4.令当前节点指向上一个节点 cur_node->next = last_node; //5.令上一个节点为当前节点,当前节点为下一个结点 last_node = cur_node; cur_node = next_node; } return reverse_head_node; } void main() { LinkNode *head_ptr = new LinkNode; head_ptr->data = 0; head_ptr->next = NULL; create_link(head_ptr, 6); print_link(head_ptr, 6); LinkNode* reverse_head_node = reverse_link(head_ptr); head_ptr->next = reverse_head_node; print_link(head_ptr, 6); }
题目25分析:(合并两个排序的链表)
使用递归的方式,每次递归比较链表1和链表2的头节点,小的则为合并链表的下一个节点,并修改链表的头节点思路:
1.如果链表1头节点为空或遍历完毕,则返回链表2
2.如果链表2头节点为空或遍历完毕,则返回链表1
3.更新合并链表节点为空
4.如果链表1头节点<链表2头节点,则合并链表的节点为链表1头节点,合并链表的下一个结点是
链表1头节点下一个节点和链表2头节点比较的较小节点
5.如果链表1头节点>=链表2头节点,则合并链表的节点为链表2头节点,合并链表的下一个结点是
链表2头节点下一个节点和链表1头节点比较的较小节点
#include <iostream> using namespace std; struct LinkNode { int data; LinkNode *next; }; //创建链表 void create_link(LinkNode *head_ptr, int length) { for (int i = length; i >= 1; --i) { LinkNode *new_node = new LinkNode; new_node->data = i; new_node->next = head_ptr->next; head_ptr->next = new_node; } } //打印链表内容 void print_link(LinkNode *head_ptr, int length) { LinkNode *temp_node = head_ptr->next; while (temp_node != NULL) { cout << temp_node->data << " "; temp_node = temp_node->next; } cout << endl; } LinkNode* merge_link(LinkNode *link_1_head_node, LinkNode *link_2_head_node) { //1.如果链表1头节点为空或遍历完毕,则返回链表2 if (link_1_head_node == NULL) return link_2_head_node; //2.如果链表2头节点为空或遍历完毕,则返回链表1 else if (link_2_head_node == NULL) return link_1_head_node; //3.更新合并链表节点为空 LinkNode *merge_node = NULL; //4.如果链表1头节点<链表2头节点,则合并链表的节点为链表1头节点,合并链表的下一个结点是 //链表1头节点下一个节点和链表2头节点比较的较小节点 if (link_1_head_node->data < link_2_head_node->data) { merge_node = link_1_head_node; merge_node->next = merge_link(link_1_head_node->next, link_2_head_node); } //5.如果链表1头节点>=链表2头节点,则合并链表的节点为链表2头节点,合并链表的下一个结点是 //链表2头节点下一个节点和链表1头节点比较的较小节点 else { merge_node = link_2_head_node; merge_node->next = merge_link(link_1_head_node, link_2_head_node->next); } return merge_node;//递归结束后,返回合并链表的头节点 } void main() { LinkNode *head_ptr_1 = new LinkNode; LinkNode *head_ptr_2 = new LinkNode; head_ptr_1->data = 0; head_ptr_1->next = NULL; create_link(head_ptr_1, 6); print_link(head_ptr_1, 6); head_ptr_2->data = 0; head_ptr_2->next = NULL; create_link(head_ptr_2, 6); print_link(head_ptr_2, 6); LinkNode *merge_head_node = merge_link(head_ptr_1->next, head_ptr_2->next); head_ptr_1->next = merge_head_node; print_link(head_ptr_2, 12); }
题目26分析:(判断树B是树A的子结构)
判断树A的节点,若与B的根节点相同,则递归判断树B与树A的子结构,递归结束条件是递归到树B的叶节点;若不相同则递归判断树A的节点和树B的节点
思路:
1.递归遍历树A的节点,截止条件是树A或B到达叶节点
2.判断树A的节点与树B的节点是否相同
3.若不相同则递归判断树A的左子节点和树B的根节点
4.若不相同则递归判断树A的右子节点和树B的根节点
5.若相同,则递归判断此时树A的左右子节点与树B左右子节点,递归截止条件是树B到达叶节点
#include <iostream> #include <string> using namespace std; struct BTNode { int data; BTNode *lchild, *rchild; }; BTNode* create_tree(int level, string pos) { int data; cout << "输入第 " << level << " 层的 " << pos << endl; cin >> data; //若输入的数据为0,则子节点为空 if (data == 0) { return NULL; } BTNode *node = new BTNode; //递归创建二叉树 node->data = data; node->lchild = create_tree(level + 1, "lchild"); node->rchild = create_tree(level + 1, "rchild"); return node; } //前序遍历 void pre_order(BTNode *T) { if(T) { cout << T->data << " ";//先访问根节点 pre_order(T->lchild);//前序遍历左子树 pre_order(T->rchild);//前序遍历右子树 } } //判断两个浮点数是否相等,使用两数差值范围判断 bool is_equal(double num1, double num2) { if ((num1-num2) >= -0.0000001&&(num1-num2) <= 0.0000001) return true; else return false; } bool is_tree_A_has_subtree_B(BTNode *root_a, BTNode *root_b) { if (root_b == NULL)//递归截止条件是树B到达叶节点,需要最先判断 return true; if (root_a == NULL)//树A已经遍历完毕,而树B还没有遍历完毕 return false; if (!is_equal(root_a->data, root_b->data))//树A和树B节点不同 return false; //对应左右子节点相同 return is_tree_A_has_subtree_B(root_a->lchild, root_b->lchild) && is_tree_A_has_subtree_B(root_a->rchild, root_b->rchild); } bool tree_A_has_subtree_B(BTNode *root_a, BTNode *root_b) { bool result = false; //1.递归遍历树A的节点,截止条件是树A或B到达叶节点 if (root_a != NULL || root_b != NULL) { //2.判断树A的节点与树B的节点是否相同 if (is_equal(root_a->data, root_b->data)) //5.若相同,则递归判断此时树A的左右子节点与树B左右子节点,递归截止条件是树B到达叶节点 result = is_tree_A_has_subtree_B(root_a, root_b); //3.若不相同则递归判断树A的左子节点和树B的根节点 if (!result) result = tree_A_has_subtree_B(root_a->lchild, root_b); //4.若不相同则递归判断树A的右子节点和树B的根节点 if(!result) result = tree_A_has_subtree_B(root_a->rchild, root_b); } return result; } void main() { BTNode *tree_A, *tree_B; cout << "输入树A:" << endl; tree_A = create_tree(1, "root"); pre_order(tree_A); cout << "树B:" << endl; tree_B = create_tree(1, "root"); pre_order(tree_B); if (tree_A_has_subtree_B(tree_A, tree_B)) cout << "\n树B是树A的子结构" << endl; }