226. Invert Binary Tree Difficult: Easy

本文介绍了一种翻转二叉树的算法实现,通过递归方式交换节点的左右子树,提供了C语言和Python两种版本的代码示例。

Invert a binary tree.

     4
   /   \
  2     7
 / \   / \
1   3 6   9

to

     4
   /   \
  7     2
 / \   / \
9   6 3   1

算法分析:可以用层序遍历的方法交换左右子树,也可以直接递归。

C语言版

struct TreeNode* invertTree(struct TreeNode* root) {
    if(root)
    {
        struct TreeNode *temp = root->right;
        root->right = invertTree(root->left);
        root->left = invertTree(temp);
    }
    return root;
}

Python版

class Solution(object):
    def invertTree(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        if root:
            root.left, root.right = self.invertTree(root.right), self.invertTree(root.left)
        return root
E:\pycharm\study\object\GUI.py:348: UserWarning: Glyph 31867 (\N{CJK UNIFIED IDEOGRAPH-7C7B}) missing from font(s) DejaVu Sans. self.probability_canvas.draw() E:\pycharm\study\object\GUI.py:348: UserWarning: Glyph 21035 (\N{CJK UNIFIED IDEOGRAPH-522B}) missing from font(s) DejaVu Sans. self.probability_canvas.draw() E:\pycharm\study\object\GUI.py:348: UserWarning: Glyph 27010 (\N{CJK UNIFIED IDEOGRAPH-6982}) missing from font(s) DejaVu Sans. self.probability_canvas.draw() E:\pycharm\study\object\GUI.py:348: UserWarning: Glyph 29575 (\N{CJK UNIFIED IDEOGRAPH-7387}) missing from font(s) DejaVu Sans. self.probability_canvas.draw() E:\pycharm\study\object\GUI.py:348: UserWarning: Glyph 20998 (\N{CJK UNIFIED IDEOGRAPH-5206}) missing from font(s) DejaVu Sans. self.probability_canvas.draw() E:\pycharm\study\object\GUI.py:348: UserWarning: Glyph 24067 (\N{CJK UNIFIED IDEOGRAPH-5E03}) missing from font(s) DejaVu Sans. self.probability_canvas.draw() E:\pycharm\study\object\GUI.py:360: UserWarning: Glyph 31867 (\N{CJK UNIFIED IDEOGRAPH-7C7B}) missing from font(s) DejaVu Sans. self.chart_canvas.draw() E:\pycharm\study\object\GUI.py:360: UserWarning: Glyph 21035 (\N{CJK UNIFIED IDEOGRAPH-522B}) missing from font(s) DejaVu Sans. self.chart_canvas.draw() E:\pycharm\study\object\GUI.py:360: UserWarning: Glyph 27010 (\N{CJK UNIFIED IDEOGRAPH-6982}) missing from font(s) DejaVu Sans. self.chart_canvas.draw() E:\pycharm\study\object\GUI.py:360: UserWarning: Glyph 29575 (\N{CJK UNIFIED IDEOGRAPH-7387}) missing from font(s) DejaVu Sans. self.chart_canvas.draw() E:\pycharm\study\object\GUI.py:360: UserWarning: Glyph 20998 (\N{CJK UNIFIED IDEOGRAPH-5206}) missing from font(s) DejaVu Sans. self.chart_canvas.draw() E:\pycharm\study\object\GUI.py:360: UserWarning: Glyph 24067 (\N{CJK UNIFIED IDEOGRAPH-5E03}) missing from font(s) DejaVu Sans. self.chart_canvas.draw() 单独写一个类调用
最新发布
06-24
<think>我们注意到,尽管之前已经尝试设置中文字体,但问题仍然出现。这可能是因为在设置全局字体时,没有正确应用到每个图表实例。此外,我们可能需要强制刷新字体缓存,并确保在创建图表时使用正确的字体属性。下面,我们将单独写一个类来管理Matplotlib的字体设置,并在每次绘图时确保使用支持中文的字体。我们将创建一个名为`FontManager`的类,它负责:1.在初始化时设置Matplotlib的默认字体(支持中文)2.提供方法来获取当前可用的中文字体属性3.在每次绘图前确保使用正确的字体同时,我们将修改绘图代码,使用这个类来设置字体。注意:由于字体设置是全局的,我们只需要在程序启动时初始化一次。但是,为了确保在运行时也能动态调整字体,我们将提供刷新机制。步骤:1.创建`FontManager`类2.在应用程序启动时初始化`FontManager`3.在绘图函数中,使用`FontManager`获取字体属性以下是具体实现:</think># 中文字体管理类解决方案 根据您的要求,我将创建一个独立的`FontManager`类来解决Matplotlib中文字符显示问题。这个类可以轻松集成到您的GUI应用中,专门处理中文字体配置和管理。 ## FontManager类实现 ```python import matplotlib as mpl import matplotlib.font_manager as fm import matplotlib.pyplot as plt import os import sys import traceback from PyQt5.QtCore import Qt from PyQt5.QtWidgets import ( QDialog, QVBoxLayout, QGroupBox, QLabel, QListWidget, QPushButton, QMessageBox, QHBoxLayout, QFontDialog ) from PyQt5.QtGui import QFont class FontManager: def __init__(self): """初始化字体管理器""" self.chinese_fonts = [] self.selected_font = None self.load_fonts() self.set_default_font() def load_fonts(self): """加载系统支持的中文字体""" self.chinese_fonts = [] try: # 获取所有系统字体 font_list = fm.findSystemFonts(fontpaths=None, fontext='ttf') for font_path in font_list: try: # 创建字体属性 font_prop = fm.FontProperties(fname=font_path) # 检查是否支持中文 if self.is_chinese_font(font_prop): font_name = font_prop.get_name() self.chinese_fonts.append({ 'name': font_name, 'path': font_path, 'prop': font_prop }) except Exception as e: print(f"加载字体 {font_path} 出错: {str(e)}") continue # 按字体名称排序 self.chinese_fonts.sort(key=lambda x: x['name']) except Exception as e: print(f"加载字体列表失败: {str(e)}") traceback.print_exc() print(f"找到 {len(self.chinese_fonts)} 个支持中文的字体") def is_chinese_font(self, font_prop): """检查字体是否支持中文""" try: # 获取字体支持的字符集 names = font_prop.get_name() # 检查是否包含中文字符集标识 if any('CJK' in name or 'Chinese' in name or '中文' in name for name in names): return True # 测试特定中文字符 test_chars = "类别概率分布" for char in test_chars: if not font_prop.get_glyph(ord(char)): return False return True except Exception: return False def set_default_font(self): """设置默认中文字体""" # 优先选择的字体列表 preferred_fonts = [ 'Microsoft YaHei', # Windows 微软雅黑 'SimHei', # Windows 黑体 'SimSun', # Windows 宋体 'PingFang SC', # macOS 苹方 'Heiti SC', # macOS 黑体 'STHeiti', # macOS 华文黑体 'WenQuanYi Micro Hei', # Linux 文泉驿微米黑 'Noto Sans CJK SC', # 思源黑体 'Source Han Sans SC' # 思源黑体 ] # 尝试使用首选字体 for font_name in preferred_fonts: if any(f['name'] == font_name for f in self.chinese_fonts): self.set_matplotlib_font(font_name) self.selected_font = font_name print(f"设置默认字体为: {font_name}") return # 如果没找到首选字体,使用第一个支持中文的字体 if self.chinese_fonts: first_font = self.chinese_fonts[0]['name'] self.set_matplotlib_font(first_font) self.selected_font = first_font print(f"设置默认字体为: {first_font}") else: print("警告: 未找到系统支持的中文字体") def set_matplotlib_font(self, font_name): """设置Matplotlib全局字体""" try: # 设置主字体 plt.rcParams['font.sans-serif'] = [font_name] # 解决负号显示问题 plt.rcParams['axes.unicode_minus'] = False # 设置默认字体大小 plt.rcParams['font.size'] = 12 # 刷新字体缓存 mpl.font_manager._rebuild() self.selected_font = font_name return True except Exception as e: print(f"设置字体失败: {str(e)}") return False def get_font_properties(self, font_name=None): """获取字体属性对象""" if not font_name: font_name = self.selected_font for font in self.chinese_fonts: if font['name'] == font_name: return font['prop'] # 如果找不到,返回默认字体属性 return fm.FontProperties() def create_font_dialog(self, parent=None): """创建字体设置对话框""" dialog = QDialog(parent) dialog.setWindowTitle("字体设置") dialog.setGeometry(300, 300, 600, 500) layout = QVBoxLayout() # 当前字体信息 info_group = QGroupBox("当前字体设置") info_layout = QVBoxLayout(info_group) current_font = self.selected_font or "未设置" font_info = f"当前字体: {current_font}\n\n" try: # 其他设置 font_info += f"字体大小: {plt.rcParams['font.size']}\n" font_info += f"负号显示: {'正常' if plt.rcParams['axes.unicode_minus'] else '可能有问题'}\n" except: pass info_label = QLabel(font_info) info_layout.addWidget(info_label) layout.addWidget(info_group) # 可用字体列表 font_group = QGroupBox("可用的中文字体") font_layout = QVBoxLayout(font_group) self.font_list = QListWidget() # 添加字体到列表 for font in self.chinese_fonts: self.font_list.addItem(f"{font['name']} - {os.path.basename(font['path'])}") font_layout.addWidget(self.font_list) # 测试和应用按钮 btn_layout = QHBoxLayout() test_btn = QPushButton("测试字体") test_btn.clicked.connect(lambda: self.test_font(dialog)) btn_layout.addWidget(test_btn) apply_btn = QPushButton("应用字体") apply_btn.clicked.connect(lambda: self.apply_font(dialog)) btn_layout.addWidget(apply_btn) font_layout.addLayout(btn_layout) layout.addWidget(font_group) # 字体大小设置 size_group = QGroupBox("字体大小") size_layout = QHBoxLayout(size_group) self.size_spin = QSpinBox() self.size_spin.setRange(8, 24) self.size_spin.setValue(plt.rcParams.get('font.size', 12)) size_layout.addWidget(QLabel("大小:")) size_layout.addWidget(self.size_spin) size_apply_btn = QPushButton("应用大小") size_apply_btn.clicked.connect(self.apply_font_size) size_layout.addWidget(size_apply_btn) layout.addWidget(size_group) # Qt字体设置 qt_group = QGroupBox("Qt界面字体") qt_layout = QHBoxLayout(qt_group) self.qt_font_btn = QPushButton("设置Qt字体...") self.qt_font_btn.clicked.connect(lambda: self.set_qt_font(parent)) qt_layout.addWidget(self.qt_font_btn) qt_label = QLabel("影响界面文字显示") qt_layout.addWidget(qt_label) layout.addWidget(qt_group) # 关闭按钮 close_btn = QPushButton("关闭") close_btn.clicked.connect(dialog.close) layout.addWidget(close_btn) dialog.setLayout(layout) return dialog def test_font(self, dialog): """测试选中的字体""" selected_item = self.font_list.currentItem() if not selected_item: QMessageBox.warning(dialog, "错误", "请先选择一个字体") return font_text = selected_item.text() font_name = font_text.split(' - ')[0] # 创建测试窗口 test_dialog = QDialog(dialog) test_dialog.setWindowTitle(f"字体测试 - {font_name}") test_dialog.setGeometry(400, 400, 500, 400) layout = QVBoxLayout() # 测试文本 test_label = QLabel("中文测试: 类别概率分布图") test_label.setAlignment(Qt.AlignCenter) # 使用Qt字体显示 qt_font = QFont(font_name, 14) test_label.setFont(qt_font) layout.addWidget(test_label) # 图表测试 fig = plt.figure(figsize=(5, 3)) canvas = FigureCanvas(fig) layout.addWidget(canvas) ax = fig.add_subplot(111) # 使用Matplotlib字体显示 font_prop = self.get_font_properties(font_name) ax.set_title("中文标题测试", fontproperties=font_prop) ax.set_xlabel("X轴标签", fontproperties=font_prop) ax.set_ylabel("Y轴标签", fontproperties=font_prop) # 绘制示例数据 x = [1, 2, 3, 4, 5] y = [2, 3, 5, 7, 11] ax.plot(x, y, 'o-') # 添加中文文本 ax.text(3, 6, "中文文本示例", fontproperties=font_prop, ha='center', va='center', fontsize=14, color='red') canvas.draw() # 关闭按钮 close_btn = QPushButton("关闭") close_btn.clicked.connect(test_dialog.close) layout.addWidget(close_btn) test_dialog.setLayout(layout) test_dialog.exec_() def apply_font(self, dialog): """应用选中的字体""" selected_item = self.font_list.currentItem() if not selected_item: QMessageBox.warning(dialog, "错误", "请先选择一个字体") return font_text = selected_item.text() font_name = font_text.split(' - ')[0] if self.set_matplotlib_font(font_name): QMessageBox.information(dialog, "成功", f"已设置字体为: {font_name}") else: QMessageBox.critical(dialog, "错误", "设置字体失败") def apply_font_size(self): """应用字体大小设置""" size = self.size_spin.value() plt.rcParams['font.size'] = size QMessageBox.information(None, "成功", f"已设置字体大小为: {size}") def set_qt_font(self, parent): """设置Qt界面字体""" font, ok = QFontDialog.getFont(QFont(), parent, "选择Qt界面字体") if ok: # 设置应用全局字体 parent.setFont(font) # 更新所有控件的字体 for widget in parent.findChildren(QWidget): widget.setFont(font) QMessageBox.information(parent, "成功", f"已设置Qt字体为: {font.family()}") ``` ## 在GUI应用中使用FontManager ### 1. 初始化FontManager 在您的GUI应用启动时初始化字体管理器: ```python class ObjectRecognitionGUI(QMainWindow): def __init__(self): super().__init__() # 初始化字体管理器 self.font_manager = FontManager() # 其他初始化代码... ``` ### 2. 添加字体设置菜单项 在菜单中添加字体设置选项: ```python class ObjectRecognitionGUI(QMainWindow): # ... 其他代码 ... def create_tools_menu(self): tool_menu = self.menuBar().addMenu("工具") # 添加字体设置菜单项 font_action = QAction("字体设置", self) font_action.triggered.connect(self.show_font_dialog) tool_menu.addAction(font_action) # 其他菜单项... def show_font_dialog(self): """显示字体设置对话框""" dialog = self.font_manager.create_font_dialog(self) dialog.exec_() ``` ### 3. 在绘图函数中使用字体管理器 在绘制图表时使用字体管理器获取正确的字体属性: ```python class ObjectRecognitionGUI(QMainWindow): # ... 其他代码 ... def plot_probability_distribution(self, features): """显示类别概率分布图 - 支持中文""" if self.classifier is None or self.classifier.classifier is None: return try: # ... 数据处理代码 ... # 创建图表 fig = self.probability_canvas.figure fig.clear() ax = fig.add_subplot(111) y_pos = np.arange(len(self.classifier.class_names)) ax.barh(y_pos, probabilities, align='center', color='skyblue') ax.set_yticks(y_pos) # 使用字体管理器获取字体属性 font_prop = self.font_manager.get_font_properties() # 设置标签使用中文字体 ax.set_yticklabels(self.classifier.class_names, fontproperties=font_prop) ax.invert_yaxis() ax.set_xlabel('概率', fontproperties=font_prop) ax.set_title('类别概率分布', fontproperties=font_prop) # 添加概率文本 for i, prob in enumerate(probabilities): ax.text(prob + 0.01, i, f"{prob*100:.1f}%", va='center', fontproperties=font_prop) self.probability_canvas.draw() except Exception as e: print(f"绘制图表时出错: {str(e)}") traceback.print_exc() ``` ### 4. 设置Qt界面字体 在应用启动时设置Qt界面字体: ```python if __name__ == "__main__": app = QApplication(sys.argv) app.setStyle("Fusion") # 初始化字体管理器 font_manager = FontManager() # 设置Qt全局字体 if sys.platform == 'win32': qt_font = QFont("Microsoft YaHei", 10) elif sys.platform == 'darwin': qt_font = QFont("PingFang SC", 10) elif sys.platform.startswith('linux'): qt_font = QFont("WenQuanYi Micro Hei", 10) else: qt_font = QFont("Arial", 10) app.setFont(qt_font) window = ObjectRecognitionGUI() window.show() sys.exit(app.exec_()) ``` ## FontManager类功能详解 1. **自动检测中文字体**: - 扫描系统所有字体 - 检测哪些字体支持中文字符 - 按名称排序便于选择 2. **智能设置默认字体**: - 优先选择常见中文字体(微软雅黑、苹方等) - 跨平台支持(Windows/macOS/Linux) - 回退机制确保总有可用字体 3. **字体测试功能**: - 预览字体效果 - 同时测试Qt和Matplotlib渲染 - 显示中文标题、标签和文本 4. **完整字体管理**: - 设置Matplotlib全局字体 - 设置字体大小 - 设置Qt界面字体 - 应用更改无需重启 5. **用户友好界面**: - 直观的字体列表 - 清晰的当前设置显示 - 一键测试和应用 ## 使用示例 ```python # 初始化字体管理器 font_manager = FontManager() # 获取当前字体属性 font_prop = font_manager.get_font_properties() # 在绘图时使用 ax.set_title("中文标题", fontproperties=font_prop) # 显示字体设置对话框 dialog = font_manager.create_font_dialog(parent_window) dialog.exec_() ``` ## 优势与特点 1. **独立封装**:作为独立类,易于集成到任何PyQt应用中 2. **跨平台支持**:自动适应Windows/macOS/Linux系统 3. **智能检测**:准确识别支持中文的字体 4. **用户友好**:提供图形界面进行字体管理 5. **无需重启**:更改字体设置后立即生效 6. **全面控制**:同时管理Matplotlib和Qt字体 这个`FontManager`类解决了Matplotlib中文显示问题,同时提供了友好的界面让用户选择和测试字体,确保您的GUI应用在各种环境下都能正确显示中文字符。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值