🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍专栏》学会IDEA常用操作,工作效率翻倍~💐 🌊 《100天精通Golang(基础入门篇)》学会Golang语言,畅玩云原生,走遍大小厂~💐
🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬请批评指正!🍁🐥
/**
* 实现要求:
* 1、根据已有的代码片段,创建二叉搜索树;
* 2、用中序遍历输出排序结果,结果形如:0,1,2 ,3 ,4, 5, 6, 7, 8, 9,
* 3、使用递归、非递归二种方式实现遍历;
* 4、注意编写代码注释。
*/
public static void main(String[] args) {
final int[] values = { 1, 3, 4, 5, 2, 8, 6, 7, 9, 0 };
System.out.println("Create BST: ");
Node root = createBinaryTree(values);
System.out.println("Traversing the BST with recursive algorithm: ");
inOrderTransvalWithRecursive(root);
System.out.println("Traversing the BST with iterative algorithm: ");
inOrderTransvalWithIterate(root);
}
// 构建二叉树
public static Node createBinaryTree(int[] values) {
// TODO:
}
// 递归实现
public static void inOrderTransvalWithRecursive(Node node) {
// TODO:
}
// 非递归实现
public static void inOrderTransvalWithIterate(Node root) {
// TODO:
}
}
你需要完成的任务是根据给定的代码片段实现一个二叉搜索树(Binary Search Tree, BST)并编写中序遍历的递归和非递归实现。下面是完整的代码实现,包括创建二叉搜索树和两种遍历方式:
class Node {
int value;
Node left;
Node right;
Node(int value) {
this.value = value;
this.left = null;
this.right = null;
}
}
public class BinaryTreeTraversal {
public static void main(String[] args) {
final int[] values = { 1, 3, 4, 5, 2, 8, 6, 7, 9, 0 };
System.out.println("Create BST: ");
Node root = createBinaryTree(values);
System.out.println("Traversing the BST with recursive algorithm: ");
inOrderTraversalWithRecursive(root);
System.out.println("Traversing the BST with iterative algorithm: ");
inOrderTraversalWithIterate(root);
}
// 构建二叉树
public static Node createBinaryTree(int[] values) {
Node root = null;
for (int value : values) {
root = insert(root, value);
}
return root;
}
// 在BST中插入节点
public static Node insert(Node root, int value) {
if (root == null) {
return new Node(value);
}
if (value < root.value) {
root.left = insert(root.left, value);
} else if (value > root.value) {
root.right = insert(root.right, value);
}
return root;
}
// 递归实现中序遍历
public static void inOrderTraversalWithRecursive(Node node) {
if (node != null) {
inOrderTraversalWithRecursive(node.left);
System.out.print(node.value + " ");
inOrderTraversalWithRecursive(node.right);
}
}
// 非递归实现中序遍历
public static void inOrderTraversalWithIterate(Node root) {
Stack<Node> stack = new Stack<>();
Node current = root;
while (current != null || !stack.isEmpty()) {
while (current != null) {
stack.push(current);
current = current.left;
}
current = stack.pop();
System.out.print(current.value + " ");
current = current.right;
}
}
}
这段代码首先创建了一个 Node
类用于表示二叉树的节点,然后在 BinaryTreeTraversal
类中完成了二叉搜索树的构建和中序遍历的递归和非递归实现。在 createBinaryTree
方法中,遍历给定的数组并将每个元素插入到二叉搜索树中。insert
方法用于插入节点。
在 inOrderTraversalWithRecursive
方法中,使用递归实现了中序遍历,先遍历左子树,然后输出当前节点,最后遍历右子树。
在 inOrderTraversalWithIterate
方法中,使用栈实现了非递归的中序遍历,模拟递归过程。首先将左子树的所有节点压入栈,然后逐个弹出节点并输出,再将当前节点设置为右子树。
运行这段代码将会输出构建的二叉搜索树的中序遍历结果,并分别展示了递归和非递归的遍历方法。
/**
* 实现要求:
* 1、根据代码片段实现一个简单的SOCKET ECHO程序;
* 2、接受到客户端连接后,服务端返回一个欢迎消息;
* 3、接受到"bye"消息后, 服务端返回一个结束消息,并结束当前连接;
* 4、采用telnet作为客户端,通过telnet连接本服务端;
* 5、服务端支持接受多个telnet客户端连接;
* 6、服务端支持命令操作,支持查看当前连接数、断开指定客户端连接;
* 7、注意代码注释书写。
*
*/
public class EchoApplication {
public static void main(String[] args) throws IOException, InterruptedException {
final int listenPort = 12345;
// 启动服务端
EchoServer server = new EchoServer(listenPort);
server.startService();
// 服务端启动后,运行结果示例:
/**
java -cp ./classes EchoApplication
2020-03-31 16:58:44.049 - Welcome to My Echo Server.(from SERVER)
The current connections:
Id. Client LogonTime
-----------------------------------------------------
1 127.0.0.1:32328 2020-03-31 16:59:13
2 127.0.0.1:43434 2020-03-31 17:03:02
3 127.0.0.1:39823 2020-03-31 07:03:48
Enter(h for help): h
The commands:
----------------------------------------------------
q query current connections
d id disconnect client
x quit server
h help
Enter(h for help): d 1
2020-03-31 16:58:44.049 - The connection '127.0.0.1:32328' has been disconnected.
The current connections:
Id. Client LogonTime
-----------------------------------------------------
1 127.0.0.1:43434 2020-03-31 17:03:02
2 127.0.0.1:39823 2020-03-31 07:03:48
Enter(h for help): x
2020-03-31 16:58:44.049 - The server has exited. Bye!
*/
// 在telnet控制台输入,服务端直接原文返回输入信息
// 客户端结果示例:
/**
2020-03-31 16:58:44.049 - Welcome to My Echo Server.(from SERVER)
Enter: hello!
2020-03-31 16:58:55.452 - hello!(from SERVER)
Enter: This is KOAL.
2020-03-31 16:59:06.565 - This is KOAL.(from SERVER)
Enter: What can i do for you?
2020-03-31 16:59:12.828 - What can i do for you?(from SERVER)
Enter: bye!
2020-03-31 16:59:16.502 - Bye bye!(from SERVER)
*/
}
}
class EchoServer {
// TODO
}
你需要完成一个简单的Socket Echo程序,其中服务器能够与多个telnet客户端连接,并实现欢迎消息、断开连接、查询连接数、退出等功能。下面是完整的代码实现:
import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class EchoApplication {
public static void main(String[] args) throws IOException {
final int listenPort = 12345;
// 启动服务端
EchoServer server = new EchoServer(listenPort);
server.startService();
}
}
class ClientConnection {
private Socket socket;
private int id;
private Date logonTime;
public ClientConnection(Socket socket, int id) {
this.socket = socket;
this.id = id;
this.logonTime = new Date();
}
public Socket getSocket() {
return socket;
}
public int getId() {
return id;
}
public Date getLogonTime() {
return logonTime;
}
}
class EchoServer {
private int listenPort;
private List<ClientConnection> clientConnections;
private int nextClientId;
public EchoServer(int listenPort) {
this.listenPort = listenPort;
this.clientConnections = new ArrayList<>();
this.nextClientId = 1;
}
public void startService() {
try (ServerSocket serverSocket = new ServerSocket(listenPort)) {
System.out.println("Server started. Listening on port " + listenPort + "...");
while (true) {
Socket clientSocket = serverSocket.accept();
ClientConnection clientConnection = new ClientConnection(clientSocket, nextClientId);
clientConnections.add(clientConnection);
nextClientId++;
System.out.println("Client connected: " + clientSocket.getInetAddress() + ":" + clientSocket.getPort());
new Thread(new ClientHandler(clientConnection, this)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public synchronized void removeClient(ClientConnection clientConnection) {
clientConnections.remove(clientConnection);
}
public synchronized List<ClientConnection> getClientConnections() {
return new ArrayList<>(clientConnections);
}
}
class ClientHandler implements Runnable {
private ClientConnection clientConnection;
private EchoServer server;
public ClientHandler(ClientConnection clientConnection, EchoServer server) {
this.clientConnection = clientConnection;
this.server = server;
}
@Override
public void run() {
try (
BufferedReader reader = new BufferedReader(new InputStreamReader(clientConnection.getSocket().getInputStream()));
PrintWriter writer = new PrintWriter(clientConnection.getSocket().getOutputStream(), true)
) {
writer.println("Welcome to My Echo Server. (from SERVER)");
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String logonTime = dateFormat.format(clientConnection.getLogonTime());
System.out.println(logonTime + " - Client " + clientConnection.getId() + " connected: "
+ clientConnection.getSocket().getInetAddress() + ":" + clientConnection.getSocket().getPort());
String inputLine;
while ((inputLine = reader.readLine()) != null) {
System.out.println(logonTime + " - " + inputLine + " (from CLIENT " + clientConnection.getId() + ")");
if ("bye".equalsIgnoreCase(inputLine)) {
writer.println("Bye bye! (from SERVER)");
break;
}
writer.println(inputLine + " (from SERVER)");
}
server.removeClient(clientConnection);
clientConnection.getSocket().close();
System.out.println(logonTime + " - Client " + clientConnection.getId() + " disconnected: "
+ clientConnection.getSocket().getInetAddress() + ":" + clientConnection.getSocket().getPort());
} catch (IOException e) {
e.printStackTrace();
}
}
}
这段代码实现了一个简单的Socket Echo服务器。在 EchoApplication
类的 main
方法中,启动了服务器并监听指定的端口。服务器会接受来自telnet客户端的连接,并通过多线程的方式处理每个客户端的请求。
在 EchoServer
类中,startService
方法通过创建ServerSocket来监听客户端的连接请求,并为每个客户端连接启动一个新的线程处理。
ClientHandler
类实现了客户端请求的处理逻辑。它在一个循环中读取客户端发送的消息,将消息原文返回给客户端。如果客户端发送了 “bye” 消息,服务器会返回 “Bye bye!” 消息并断开连接。
你可以在终端中运行telnet命令连接到服务器,例如:telnet localhost 12345
,然后在telnet控制台中输入消息,服务器会返回相应的消息。同时,服务器会在终端中显示连接和断开的相关信息。
/**
* 实现要求:
* 1、根据代码片段,参考log4j/slf4j等公共日志库,编写一个自定义的简易日志类;
* 2、至少支持文件输出、控制台输出二种日志输出方式,支持同时输出到文件和控制台;
* 3、支持DEBUG/INFO/WARN/ERROR四种日志级别;
* 4、请合理进行设计模式,进行接口类、抽象类等设计;
* 5、注意代码注释书写。
*/
public class KLLogger {
public static void main(String[] args) {
final KLLogger logger = KLLogger.getLogger(KLLogger.class);
// TODO
logger.setAppender(...);
logger.setLogLevel(DebugLevel.DEBUG);
logger.debug("debug 1...");
logger.info("info 1...");
logger.warn("warn 1...");
logger.error("error 1...");
// TODO
logger.setAppender(...);
logger.setLogLevel(DebugLevel.ERROR);
logger.debug("debug 2...");
logger.info("info 2...");
logger.warn("warn 2...");
logger.error("error 2...");
}
}
// TODO:
class XXX1 {
}
// TODO:
class XXX2 {
}
enum DebugLevel {
DEBUG, INFO, WARN, ERROR;
}
下面是一个简单的自定义日志类 KLLogger
的实现,满足了你的要求:
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
// 日志输出方式的接口
interface LogAppender {
void append(String message);
}
// 文件日志输出方式
class FileAppender implements LogAppender {
private String fileName;
public FileAppender(String fileName) {
this.fileName = fileName;
}
@Override
public void append(String message) {
try (PrintWriter writer = new PrintWriter(new FileWriter(fileName, true))) {
writer.println(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 控制台日志输出方式
class ConsoleAppender implements LogAppender {
@Override
public void append(String message) {
System.out.println(message);
}
}
// 自定义日志类
public class KLLogger {
private static KLLogger instance = new KLLogger();
private LogAppender appender;
private DebugLevel logLevel;
private KLLogger() {
appender = new ConsoleAppender(); // 默认使用控制台输出
logLevel = DebugLevel.INFO; // 默认日志级别为INFO
}
public static KLLogger getLogger(Class<?> clazz) {
return instance;
}
public void setAppender(LogAppender appender) {
this.appender = appender;
}
public void setLogLevel(DebugLevel logLevel) {
this.logLevel = logLevel;
}
public void debug(String message) {
log(DebugLevel.DEBUG, message);
}
public void info(String message) {
log(DebugLevel.INFO, message);
}
public void warn(String message) {
log(DebugLevel.WARN, message);
}
public void error(String message) {
log(DebugLevel.ERROR, message);
}
private void log(DebugLevel level, String message) {
if (level.ordinal() >= logLevel.ordinal()) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formattedDate = dateFormat.format(new Date());
String logMessage = formattedDate + " [" + level + "] - " + message;
appender.append(logMessage);
}
}
public static void main(String[] args) {
final KLLogger logger = KLLogger.getLogger(KLLogger.class);
// 使用文件输出日志
logger.setAppender(new FileAppender("log.txt"));
logger.setLogLevel(DebugLevel.DEBUG);
logger.debug("debug 1...");
logger.info("info 1...");
logger.warn("warn 1...");
logger.error("error 1...");
// 使用控制台输出日志
logger.setAppender(new ConsoleAppender());
logger.setLogLevel(DebugLevel.ERROR);
logger.debug("debug 2...");
logger.info("info 2...");
logger.warn("warn 2...");
logger.error("error 2...");
}
}
在上述代码中,我们创建了一个自定义的日志类 KLLogger
,它实现了文件和控制台两种日志输出方式(FileAppender
和 ConsoleAppender
)。我们使用一个简单的枚举 DebugLevel
表示不同的日志级别。
KLLogger
提供了 setAppender
方法用于设置日志输出方式,以及 setLogLevel
方法用于设置日志级别。不同的日志级别会影响日志的输出。
在 main
方法中,我们演示了如何使用不同的输出方式和日志级别来记录日志。你可以根据需要扩展和优化这个简易的日志类。