그래프를 그려보겠습니다.
알고리즘 시간에 많이 나오는 시간 복잡도 그래프를 프로그램으로 그려보려고 합니다. 물론 어떤 함수도 그릴 수 있습니다.
최종 프로그램의 모습입니다. x 축은 800까지 표시하고, y축은 6000까지 표시하도록 했습니다. 실제 nlogn 이나 n^2 정도만 되어도 매우 큰 값이 되기 때문에 y 축은 크기를 1/10으로 축소해서 그렸습니다. 즉 픽셀 하나가 10의 값이 됩니다.
그래프가 그려지는 모습을 보기위해서 타이머를 사용했습니다. 0.01초에 한개의 점씩 그려줍니다. x 축이나 y축의 범위를 넘어서면 타이머를 Stop 시킵니다.
WPF 파일은 다음과 같습니다.
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TimeComplexity" SizeToContent="WidthAndHeight" ResizeMode="CanMinimize">
<Grid Margin="10" VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Canvas Grid.Row="0" Grid.Column="1" Name="Plotter" Width="800" Height="600" ClipToBounds="True">
<Polyline Name="logLine" Stroke="LightSteelBlue" StrokeThickness="2.0" />
<Polyline Name="linearLine" Stroke="SteelBlue" StrokeThickness="2.0" />
<Polyline Name="nlogLine" Stroke="LightSteelBlue" StrokeThickness="1.0" />
<Polyline Name="quadraticLine" Stroke="SteelBlue" StrokeThickness="2.0" />
<Polyline Name="cubicLine" Stroke="LightSteelBlue" StrokeThickness="2.0" />
<Polyline Name="expLine" Stroke="Red" StrokeThickness="1.0" />
<Polyline Name="GridLine" Stroke="Black" StrokeThickness="1.0" StrokeDashArray="4 3" />
</Canvas>
<TextBlock Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right">N</TextBlock>
<TextBlock Grid.Row="0" Grid.Column="0" HorizontalAlignment="Left">f</TextBlock>
<TextBlock Grid.Row="1" Grid.Column="0" HorizontalAlignment="Right">0</TextBlock>
<TextBlock Grid.Row="0" Grid.Column="1" HorizontalAlignment="Center" FontSize="20">Time Complexity Graphs</TextBlock>
<Line Stroke="Black" Y2="600" StrokeThickness="2" HorizontalAlignment="Right" VerticalAlignment="Stretch"/>
<Line Grid.Column="1" Stroke="Black" X2="800" StrokeThickness="2" VerticalAlignment="Bottom" HorizontalAlignment="Stretch"/>
<StackPanel Grid.Row="2" Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Center">
<Button Width="70" Margin="10,0,10,10" Click="logN_Click">logN</Button>
<Button Width="70" Margin="10,0,10,10" Click="N_Click">N</Button>
<Button Width="70" Margin="10,0,10,10" Click="NlogN_Click">NlogN</Button>
<Button Width="70" Margin="10,0,10,10" Click="N2_Click">N^2</Button>
<Button Width="70" Margin="10,0,10,10" Click="N3_Click">N^3</Button>
<Button Width="70" Margin="10,0,10,10" Click="eN_Click">2^N</Button>
<Button Width="70" Margin="10,0,10,10" Click="All_Click">All</Button>
<Button Width="70" Margin="10,0,10,10" Click="Quit_Click">Quit</Button>
</StackPanel>
</Grid>
</Window>
C# 파일입니다. 먼저 Canvas에 그리드와 축을 그립니다.
public MainWindow()
{
InitializeComponent();
DrawGridLine();
DrawAxis();
}
private void DrawGridLine()
{
for (int i = 100; i < Plotter.Width; i += 100)
{
Line l = new Line();
l.X1 = i; l.Y1 = 0;
l.X2 = i; l.Y2 = Plotter.Height;
l.Stroke = Brushes.LightGreen;
l.StrokeDashArray = DoubleCollection.Parse("4, 3");
Plotter.Children.Add(l);
}
for (int i = 100; i < Plotter.Width; i += 100)
{
Line l = new Line();
l.X1 = 0; l.Y1 = i;
l.X2 = Plotter.Width; l.Y2 = i;
l.Stroke = Brushes.LightGreen;
l.StrokeDashArray = DoubleCollection.Parse("4, 3");
Plotter.Children.Add(l);
}
}
private void DrawAxis()
{
for (int i = 1; i <= 6; i++) // 세로축
{
TextBlock txt = new TextBlock();
txt.Text = (i * 1000).ToString();
txt.Margin = new Thickness(10, Plotter.Height - i*100, 0, 0);
Plotter.Children.Add(txt);
}
for (int i = 1; i <= 8; i++) // 가로축
{
TextBlock txt = new TextBlock();
txt.Text = (i * 100).ToString();
if(i==8)
txt.Margin = new Thickness(i * 100 - 20, Plotter.Height - 20, 0, 0);
else
txt.Margin = new Thickness(i*100, Plotter.Height - 20, 0, 0);
Plotter.Children.Add(txt);
}
}
다음은 각 함수에 대한 타이머를 정의하고, 버튼이 눌렸을 때의 이벤트처리함수를 하나씩 만들어 줍니다.
DispatcherTimer tLog = null;
DispatcherTimer tN = null;
DispatcherTimer tNLog = null;
DispatcherTimer tN2 = null;
DispatcherTimer tN3 = null;
DispatcherTimer teN = null;
// ----------------------------------------------------------------------Log
private void logN_Click(object sender, RoutedEventArgs e)
{
tLog = new DispatcherTimer();
tLog.Interval = new TimeSpan(0, 0, 0, 0, 10); // 0.01초
tLog.Tick += tLog_Tick;
tLog.Start();
}
double x = 1.0;
double dx = 1.0;
void tLog_Tick(object sender, EventArgs e)
{
x += dx;
if (x >= Plotter.Width)
{
tLog.Stop();
TextBlock txt = new TextBlock();
txt.Text = "Log(" + x.ToString() + ") = " + Math.Log(x, 2.0).ToString();
txt.Margin = new Thickness(600, 100, 0, 0);
Plotter.Children.Add(txt);
}
logLine.Points.Add(new Point(x, Plotter.Height - Math.Log(x, 2.0)));
Console.WriteLine("{0} {1}", x, Math.Log(x, 2.0));
}
위의 코드는 로그함수를 처리한 것입니다. 다른 모든 버튼에도 위와 같이 함수를 만들어 줍니다. 그래프로 그릴 함수가 6개인데, 처리하는 부분이 모두 비슷합니다. 더 효율적으로 코딩할 방법이 있을 것 같은데... 알려주시면 감사하겠습니다.
BeeEye Dmu
'C# WPF' 카테고리의 다른 글
[C# WPF] 데이터베이스 만들기(ACCESS) (1) | 2013.12.04 |
---|---|
[C# WPF] 우편번호 찾기 DB 프로그램(Access DB 사용) (0) | 2013.12.03 |
C#, WPF 점선그리는 법 (0) | 2013.11.27 |
C# WPF delay 주는 방법 (0) | 2013.11.22 |
C# WPF 카드게임(Memory Card Game) (0) | 2013.11.22 |