hello-algo/codes/cpp/include/PrintUtil.hpp
Gonglja b9e97d3823
Fix access error when printArray(arr, 0) (#432)
* fix(codes/cpp): Memory leak fix: the space was not freed when pop removed the element.

* fix(codes/cpp): Fix access error when printArray(arr, 0)

* Update PrintUtil.hpp

---------

Co-authored-by: Yudong Jin <krahets@163.com>
2023-03-20 21:26:20 +08:00

339 lines
8.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* File: PrintUtil.hpp
* Created Time: 2021-12-19
* Author: Krahets (krahets@163.com), msk397 (machangxinq@gmail.com), LoneRanger(836253168@qq.com)
*/
#pragma once
#include <iostream>
#include <string>
#include <sstream>
#include <climits>
#include "ListNode.hpp"
#include "TreeNode.hpp"
/**
* @brief Expose the underlying storage of the priority_queue container
*
* @tparam T
* @tparam S
* @tparam C
* @param pq
* @return S
*/
template <typename T, typename S, typename C>
S &Container(priority_queue<T, S, C> &pq) {
struct HackedQueue : private priority_queue<T, S, C>
{
static S &Container(priority_queue<T, S, C> &pq)
{
return pq.*&HackedQueue::c;
}
};
return HackedQueue::Container(pq);
}
class PrintUtil {
public:
/**
* @brief Find an element in a vector
*
* @tparam T
* @param vec
* @param ele
* @return int
*/
template <typename T>
static int vecFind(const vector<T>& vec, T ele) {
int j = INT_MAX;
for (int i = 0; i < vec.size(); i++) {
if (vec[i] == ele) {
j = i;
}
}
return j;
}
/**
* @brief Concatenate a vector with a delim
*
* @tparam T
* @param delim
* @param vec
* @return string
*/
template <typename T>
static string strJoin(const string& delim, const T& vec) {
ostringstream s;
for (const auto& i : vec) {
if (&i != &vec[0]) {
s << delim;
}
s << i;
}
return s.str();
}
/**
* @brief Repeat a string for n times
*
* @param str
* @param n
* @return string
*/
static string strRepeat(string str, int n) {
ostringstream os;
for(int i = 0; i < n; i++)
os << str;
return os.str();
}
/**
* @brief Print an Array
*
* @tparam T
* @tparam n
*/
template<typename T>
static void printArray(T* arr, int n)
{
cout << "[";
for (int i = 0; i < n - 1; i++) {
cout << arr[i] << ", ";
}
if (n >= 1)
cout << arr[n - 1] << "]" << endl;
else
cout << "]" << endl;
}
/**
* @brief Get the Vector String object
*
* @tparam T
* @param list
* @return string
*/
template <typename T>
static string getVectorString(vector<T> &list) {
return "[" + strJoin(", ", list) + "]";
}
/**
* @brief Print a vector
*
* @tparam T
* @param list
*/
template <typename T>
static void printVector(vector<T> list) {
cout << getVectorString(list) << '\n';
}
/**
* @brief Print a vector matrix
*
* @tparam T
* @param matrix
*/
template <typename T>
static void printVectorMatrix(vector<vector<T>> &matrix) {
cout << "[" << '\n';
for (vector<T> &list : matrix)
cout << " " + getVectorString(list) + "," << '\n';
cout << "]" << '\n';
}
/**
* @brief Print a linked list
*
* @param head
*/
static void printLinkedList(ListNode *head) {
vector<int> list;
while (head != nullptr) {
list.push_back(head->val);
head = head->next;
}
cout << strJoin(" -> ", list) << '\n';
}
/**
* @brief This tree printer is borrowed from TECHIE DELIGHT
* https://www.techiedelight.com/c-program-print-binary-tree/
*/
struct Trunk {
Trunk *prev;
string str;
Trunk(Trunk *prev, string str) {
this->prev = prev;
this->str = str;
}
};
/**
* @brief Helper function to print branches of the binary tree
*
* @param p
*/
static void showTrunks(Trunk *p) {
if (p == nullptr) {
return;
}
showTrunks(p->prev);
cout << p->str;
}
/**
* @brief The interface of the tree printer
*
* @param root
*/
static void printTree(TreeNode *root) {
printTree(root, nullptr, false);
}
/**
* @brief Print a binary tree
*
* @param root
* @param prev
* @param isLeft
*/
static void printTree(TreeNode *root, Trunk *prev, bool isLeft) {
if (root == nullptr) {
return;
}
string prev_str = " ";
Trunk trunk(prev, prev_str);
printTree(root->right, &trunk, true);
if (!prev) {
trunk.str = "———";
}
else if (isLeft) {
trunk.str = "/———";
prev_str = " |";
}
else {
trunk.str = "\\———";
prev->str = prev_str;
}
showTrunks(&trunk);
cout << " " << root->val << endl;
if (prev) {
prev->str = prev_str;
}
trunk.str = " |";
printTree(root->left, &trunk, false);
}
/**
* @brief Print a stack
*
* @tparam T
* @param stk
*/
template <typename T>
static void printStack(stack<T> stk) {
// Reverse the input stack
stack<T> tmp;
while(!stk.empty()) {
tmp.push(stk.top());
stk.pop();
}
// Generate the string to print
ostringstream s;
bool flag = true;
while(!tmp.empty()) {
if (flag) {
s << tmp.top();
flag = false;
}
else s << ", " << tmp.top();
tmp.pop();
}
cout << "[" + s.str() + "]" << '\n';
}
/**
* @brief
*
* @tparam T
* @param queue
*/
template <typename T>
static void printQueue(queue<T> queue)
{
// Generate the string to print
ostringstream s;
bool flag = true;
while(!queue.empty()) {
if (flag) {
s << queue.front();
flag = false;
}
else s << ", " << queue.front();
queue.pop();
}
cout << "[" + s.str() + "]" << '\n';
}
template <typename T>
static void printDeque(deque<T> deque) {
// Generate the string to print
ostringstream s;
bool flag = true;
while(!deque.empty()) {
if (flag) {
s << deque.front();
flag = false;
}
else s << ", " << deque.front();
deque.pop_front();
}
cout << "[" + s.str() + "]" << '\n';
}
/**
* @brief Print a HashMap
*
* @tparam TKey
* @tparam TValue
* @param map
*/
// 定义模板参数 TKey 和 TValue用于指定键值对的类型
template <typename TKey, typename TValue>
static void printHashMap(unordered_map<TKey,TValue> map) {
for (auto kv : map) {
cout << kv.first << " -> " << kv.second << '\n';
}
}
/**
* @brief Print a Heap (PriorityQueue)
*
* @tparam T
* @tparam S
* @tparam C
* @param heap
*/
template <typename T, typename S, typename C>
static void printHeap(priority_queue<T, S, C> &heap) {
vector<T> vec = Container(heap);
cout << "堆的数组表示:";
printVector(vec);
cout << "堆的树状表示:" << endl;
TreeNode *root = vecToTree(vec);
printTree(root);
freeMemoryTree(root);
}
};