No. 12 - Mirror of Binary Trees

No. 12 - Mirror of Binary Trees


Problem: Please implement a function which returns mirror of a binary tree.

Binary tree nodes are defined as:

struct BinaryTreeNode
{
     int                    m_nValue;
    BinaryTreeNode*        m_pLeft; 
    BinaryTreeNode*        m_pRight;
};

Analysis: Mirror of binary trees may be a new concept for many candidates, so they may not find a solution in short time during interviews. In order to get some visual ideas about mirrors, we may draw a binary tree and its mirror according to our daily experience. For example, the binary tree on the right of Figure 1 is the mirror of the left one.


Let us analyze these two trees in Figure 1 carefully to get the steps of mirrors. Their root nodes are identical, but their left and right children are swapped. Firstly we may swap two nodes under the root of the original binary tree, and it becomes the second tree in Figure 2.


We can notice that the children nodes of not 10 and 6 keep unchanged. Therefore, we need to continue to swap their children nodes. The third and fourth trees in Figure 2 are the swapped binary trees accordingly. It is noticeable that the fourth tree is the mirror target.

Now we can summarize the process for mirror: We visit all nodes in a binary tree with pre-order traversal, and swap the children of current visited node if it has. We will get mirror of a binary tree after we visit all of its nodes.

Let us begin to write code after we get clear ideas about the process. The following is the sample code:

void Mirror(BinaryTreeNode *pNode)
{
     if((pNode == NULL) || (pNode->m_pLeft == NULL && pNode->m_pRight))
         return;

    BinaryTreeNode *pTemp = pNode->m_pLeft;
    pNode->m_pLeft = pNode->m_pRight;
    pNode->m_pRight = pTemp;
   
     if(pNode->m_pLeft)
        MirrorRecursively(pNode->m_pLeft); 

     if(pNode->m_pRight)
        MirrorRecursively(pNode->m_pRight);
}

The author Harry He owns all the rights of this post. If you are going to use part of or the whole of this ariticle in your blog or webpages,  please add a referenced to http://codercareer.blogspot.com/. If you are going to use it in your books, please contact me (zhedahht@gmail.com) . Thanks.

<think>我们使用PyInstaller打包时,默认情况下控制台程序会显示一个黑色控制台窗口。如果不希望显示这个窗口,我们应该使用`--noconsole`选项(或者`-w`选项,这是它的简写形式)。因此,修改你的命令,添加`--noconsole`参数即可。修改后的命令如下:```bashpyinstaller--onefile--noconsole^--add-binary"C:\Windows\System32\ucrtbase.dll;."^--add-binary"C:\Windows\System32\downlevel\api-ms-win-crt-runtime-l1-1-0.dll;."^--add-binary"C:\python3.8.10\python38.dll;."^main.py```注意:在Windows命令提示符中,我们使用`^`作为行续接符。在Linux或macOS的终端中,我们使用`\`。如果你在PowerShell中运行,需要将续接符改为`(反引号)并且每行末尾加上空格和反引号。对于PowerShell,命令可以这样写:```powershellpyinstaller--onefile--noconsole`--add-binary"C:\Windows\System32\ucrtbase.dll;."`--add-binary"C:\Windows\System32\downlevel\api-ms-win-crt-runtime-l1-1-0.dll;."`--add-binary"C:\python3.8.10\python38.dll;."`main.py```解释:-`--noconsole`(或`-w`)选项告诉PyInstaller不要为应用程序提供控制台窗口。这适用于GUI应用程序或不希望显示控制台窗口的情况。但是请注意,如果你的程序有控制台输出(如print语句),使用`--noconsole`后,这些输出将无处显示(不会弹出控制台窗口)。如果你需要捕获这些输出,可能需要重定向到文件或使用其他方式记录日志。另外,如果你的程序是控制台程序(即需要与用户通过命令行交互),那么不应该使用这个选项。另外,你添加了`python38.dll`,这通常是不必要的,因为PyInstaller会自动包含Python解释器的动态链接库。除非你有特殊原因(比如使用了自己编译的特定版本的PythonDLL),否则可以省略。最后,关于你添加的DLL文件,确保这些DLL文件确实存在于你指定的路径中。特别是`C:\Windows\System32\downlevel\api-ms-win-crt-runtime-l1-1-0.dll`,在Windows10中,这个路径是存在的,但不同系统版本可能有所不同。如果你在打包过程中遇到任何错误,请检查这些DLL文件是否存在,并确保路径正确。此外,如果你希望程序在运行时完全不显示任何窗口(包括可能由GUI框架创建的主窗口),那么你需要确保你的GUI代码不会创建可见窗口。但通常`--noconsole`只影响控制台窗口,不影响GUI窗口。例如,如果你使用Tkinter,PyQt,wxPython等GUI库,那么使用`--noconsole`后,控制台窗口不会出现,但GUI窗口会正常出现。总结:添加`--noconsole`选项即可。下面是一个完整的例子(在命令提示符中):```cmdpyinstaller--onefile--noconsole--add-binary"C:\Windows\System32\ucrtbase.dll;."--add-binary"C:\Windows\System32\downlevel\api-ms-win-crt-runtime-l1-1-0.dll;."--add-binary"C:\python3.8.10\python38.dll;."main.py```如果你使用spec文件,可以在spec文件中设置`console=False`。例如,在spec文件的`EXE`初始化中:```pythonexe=EXE(pyz,a.scripts,a.binaries,a.zipfiles,a.datas,[],name='main',debug=False,bootloader_ignore_signals=False,strip=False,upx=True,upx_exclude=[],runtime_tmpdir=None,console=False,#这里设置为Falseicon=None)```通过上述任一方式,打包后的程序运行将不会显示黑色控制台窗口。§§相关问题§§:1.使用PyInstaller打包时如何隐藏控制台窗口?2.PyInstaller的`--noconsole`选项对程序输出有什么影响?3.如何将控制台输出重定向到文件以避免使用`--noconsole`选项时丢失输出?4.使用PyInstaller打包GUI应用程序的最佳实践是什么?</think>### 解决 PyInstaller 打包时弹出黑色控制台窗口的问题 当您使用 PyInstaller 打包 Python 程序时,默认会生成控制台应用程序(显示黑色命令窗口)。要去除这个窗口,需要使用 `--noconsole` 或 `-w` 参数。 #### 修改后的打包命令 ```bash pyinstaller --onefile --noconsole ^ --add-binary "C:\Windows\System32\ucrtbase.dll;." ^ --add-binary "C:\Windows\System32\downlevel\api-ms-win-crt-runtime-l1-1-0.dll;." ^ --add-binary "C:\python3.8.10\python38.dll;." ^ main.py ``` #### 关键修改: 1. **添加 `--noconsole` 参数**: - 这会告诉 PyInstaller 创建一个 Windows GUI 应用程序,而不是控制台应用程序 - 等价于 `-w` 短参数形式 2. **其他等效写法**: ```bash # 使用短参数形式 pyinstaller -F -w ... # 在 spec 文件中设置 exe = EXE(..., console=False, ...) ``` ### 深入解析控制台窗口问题 #### 为什么默认会显示控制台窗口? - PyInstaller 默认创建控制台应用程序(`console=True`) - 控制台应用程序会附加到父控制台(如果有)或创建新控制台窗口 - 对于 GUI 应用,这会导致不必要的黑色窗口 #### 无窗口应用的调试技巧 当移除控制台窗口后,您需要处理程序的输出和错误: ```python # 在 main.py 中添加日志系统 import logging import sys import os def setup_logging(): """配置日志系统到文件""" log_dir = os.path.join(os.getenv('APPDATA'), 'MyApp', 'Logs') os.makedirs(log_dir, exist_ok=True) log_file = os.path.join(log_dir, 'app.log') logging.basicConfig( filename=log_file, level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s' ) # 捕获未处理异常 def handle_exception(exc_type, exc_value, exc_traceback): logging.error("未捕获异常", exc_info=(exc_type, exc_value, exc_traceback)) sys.exit(1) sys.excepthook = handle_exception if __name__ == "__main__": setup_logging() logging.info("应用程序启动") try: # 你的主程序代码 import my_main_module my_main_module.run() except Exception as e: logging.exception("主程序异常") finally: logging.info("应用程序退出") ``` ### 特殊场景处理 #### 1. 混合型应用(有时需要控制台) ```python import sys import ctypes def has_console(): """检测是否在控制台中运行""" kernel32 = ctypes.WinDLL('kernel32') return kernel32.GetConsoleWindow() != 0 if __name__ == "__main__": if has_console(): # 在控制台中运行时显示输出 print("控制台模式") else: # GUI模式 pass ``` #### 2. 使用 `--windowed` 参数(PyInstaller 别名) ```bash # --windowed 等同于 --noconsole pyinstaller --windowed --onefile ... ``` ### 完整打包示例(带错误处理) ```bash @echo off set PYTHON_PATH=C:\python3.8.10 set DLL_PATH=C:\Windows\System32 pyinstaller --onefile --noconsole ^ --add-binary "%DLL_PATH%\ucrtbase.dll;." ^ --add-binary "%DLL_PATH%\downlevel\api-ms-win-crt-runtime-l1-1-0.dll;." ^ --add-binary "%PYTHON_PATH%\python38.dll;." ^ --hidden-import=optional_module ^ --name "MyApplication" ^ main.py if errorlevel 1 ( echo 打包失败,错误码: %errorlevel% pause exit /b %errorlevel% ) echo 打包成功,输出在 dist\MyApplication.exe ``` ### 注意事项 1. **Python 版本兼容性**: - Python 3.8.10 是您指定的版本 - 确保打包环境与目标环境一致(32位/64位) 2. **DLL 路径问题**: - `C:\Windows\System32\downlevel\` 是 Windows 10 特有的路径 - 对于 Windows 7 目标系统,建议使用其他解决方案 3. **替代方案**: ```bash # 使用 auto-py-to-exe 图形界面工具 pip install auto-py-to-exe auto-py-to-exe ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值