I simple lowpass filter will probably solve the problem. It is easy to implement and you can adjust how much you want to filter with the time constant.
Here is an example of a low-pass filter in actual code. It's technically Python but reads like pseudo-code. It takes a list of temperature values as input and outputs the filtered values as a list.
Input: input_series, time_constant
output_series = 
for current_unfiltered_value in input_series:
previous_filtered_value = output_series[-1]
B = 1.0 / time_constant
A = 1.0 - B
new_filtered_value = (A * previous_filtered_value
+ B * current_unfiltered_value)
The downside of using lowpass filters is that it introduces phase lag. The filtered value will lag slightly behind the measured signal, depending on the time constant. A highly filtered signal will lag more than a less filtered signal.
There are other filters you can use for better filtering result. For example the Kalman filter or the Alpha-beta filter. They are both model-based, which means you have to make a model for your temperature changes for it to work. There is an excellent notebook on Github that introduces these filters if you are unfamiliar with them.
I would personally go with a simple lowpass filter in the beginning. If you don't control a process based on the filtered values, but want to filter the values to make them prettier in a user interface, then that's usually more than good enough.
For eliminating runaway values I would calculate the variance of the measured signal at every timestep (you could, for example, calculate the variance for the last 50 samples). If the calculated variance passes a certain threshold then it can be assumed to be a spike, which can then be rejected.