24(反转链表)、25(合并两个排序的链表)、26(判断树B是树A的子结构)

题目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;
}

猜你喜欢

转载自blog.csdn.net/attitude_yu/article/details/80635653