Compare sorting algorithm - java

I implemented different type of sorting (bubble, insertion, selection). Know I want to compare their implementations like the following for each sort (here's an example with the bubble sort) :
For example, here's my bubble sort :
private static int[] bubbleSort(int[] tabToSort) {
int [] tab = tabToSort.clone();
boolean tabSort = false;
while(!tabSort){
tabSort = true;
for(int i = 0; i < tab.length -1; i++){
if(tab[i]> tab[i+1]){
int temp = tab[i+1];
tab[i+1] = tab[i];
tab[i] = temp;
tabSort = false;
}
}
}
return tab;
}
I started the GUI and I placed 1000 random points on it and the line y=x :
#Override
public void paintComponent (Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.BLACK);
Dimension size = getSize();
Insets insets= getInsets();
int w = size.width - insets.left - insets.right;
int h = size.height - insets.top - insets.bottom;
g2d.drawLine(size.width ,0, 0, size.height);
Random r = new Random();
for (int i =0; i < 1000; i++) {
int x = Math.abs(r.nextInt()) % w;
int y = Math.abs(r.nextInt()) % h;
Point p = new Point(x, y);
g2d.drawLine(p.x, p.y, p.x, p.y);
}
}
Here's what I've done :
Now I'm stuck, I have no idea about how to start. Could anyone indicate me the steps/ hints to follow to implement that ?
Thanks :)

You must define what the points mean. Looking at the animation, it looks like the y axis represents a value, whilst the x axis represents the position in the array of that value.
In your paint method, you would then go through the list of items and paint a dot, with the x-point being the position in the array and the y-point being a position on the y-axis. Assuming the values are within a known range.
Also, remember that the y-axis in graphics starts with 0 at the top, so you may have to do some translation of values to coordinates (depending on how you want it to look).

The easiest way would be to convert your paint method into one that uses a predefined List of points as a parameter instead of random points. On each iteration of your sort method pass the sorted array into the paint method and repaint the dots.

You'll need to
Create an int[] array with random values as a member variable. Let's call the array data. You probably want to start with a fixed array size and range of 100 each. You can adjust the values to the window size later, when a simple version is working. It may be even better to stick to a fixed size and range and just scale to the space available in paintComponent, making the behavior independent of the window size.
Change paintComponent to loop over data. The loop index is your x value and data[x] determines the y value.
Test that the code still draws the initial random array. Don't care if it is in the uppler left corner only now, you can fix that when the animation is working.
You'll need to add some kind of sleep() call to the innermost loop of your sort method, so you get a chance to observe the steps. Otherwise, even bubblesort will be too fast to observe. I'd recommend to start with one second (parameter value 1000). Make it faster later when everything works.
Start the bubbleSort method in a new thread and make sure your component gets repainted with each step. This may be the most tricky part. Perhaps hand in the component to the bublleSort method (or make bubbleSort a non-static method of the component) and let it request a repaint() at each step (fortunately, this is one of the few thread safe methods in Swing).
Fine-tune your code: Scale the x and y coordinates by multiplying with the space available and then dividing by the array size or value range. Adjust the sleep time as needed. Add support for different sorting algorithms....
If any of the steps is unclear, add a comment.

I've done this for my bachelorthesis, I did it like this (it's not perfect, but it might help you):
(I removed some unimportant methods/functions from the code below. It's mainly to illustrate how I visualized it. You can replace the GRectangle class by a simple java.awt.Point for example.)
The initialization method gives you an example of how you can find the maximum and minimum value of the data so you know how to transform your datavalues => coordinates.
public class DotVisualisation extends Visualisation {
private ArrayList<GRectangle> m_points;
private Comparable[] m_data;
private Comparable m_maxValue;
private Comparable m_minValue;
private int MAX_HEIGHT; // max height in pixels of visualization
/**
* Creates a new DotVisualisation.<br>
* <br>
* This class is a runnable JComponent that will visualize data as a function.
* The visualisation will plot the data with X and Y coordinates on the window.
* The X coordinate of the point is index of the dataelement.
* The Y coordinate of the point is relative to the value of the dataelement.<br>
* <br>
* This visualisation should be used for medium and large arrays.
*
* #author David Nysten
*/
public DotVisualisation()
{
m_points = new ArrayList<GRectangle>();
MAX_HEIGHT = 150;
}
/**
* Returns the maximum supported dimension by this visualisation.
*
* #return The supported dimension.
*/
public static int getSupportedDimension()
{
return 1;
}
#Override
public Dimension getMaximumSize()
{
return getPreferredSize();
}
#Override
public Dimension getPreferredSize()
{
return new Dimension(m_points.size() + 2, MAX_HEIGHT + 6);
}
#Override
public Dimension getMinimumSize()
{
return getPreferredSize();
}
#Override
public void paintComponent(Graphics g)
{
for(int i = 0; i < m_points.size(); ++i)
m_points.get(i).paintComponent(g);
}
private void swap(int index, int index2) { // See below }
private void initialise()
{
findMinimum();
findMaximum();
m_points.clear();
double multiplier;
int x = 0, y = 0, h;
for(int i = 0; i < m_data.length; ++i)
{
if(m_data[i].compareTo(-1) <= 0)
h = 0;
else
{
Integer value = (Integer) m_data[i];
Integer min = (Integer) m_minValue;
Integer diff = (Integer) m_maxValue - min;
multiplier = MAX_HEIGHT / diff.doubleValue();
h = (int) ((value - min) * multiplier);
}
y = (int) (MAX_HEIGHT - h);
GRectangle r = new GRectangle(x, y, 1, 1); // 1, 1 = width and height
r.setColor(Color.BLACK);
m_points.add(r);
++x;
}
}
private void findMaximum()
{
Comparable max = null;
if(m_data.length > 0)
{
max = m_data[0];
for(int i = 1; i < m_data.length; ++i)
if(m_data[i].compareTo(max) > 0)
max = m_data[i];
}
m_maxValue = max;
}
private void findMinimum()
{
Comparable min = null;
if(m_data.length > 0)
{
min = m_data[0];
for(int i = 1; i < m_data.length; ++i)
if(m_data[i].compareTo(min) < 0)
min = m_data[i];
}
m_minValue = min;
}
}
Take this into account:
Visualizing integers between 0 and 150 on a height of 150 pixels is straightforward. Visualizing a set of integers between the values 565 and 3544545 on a height of 150 is a bit less so.
PS: The code uses the index of the element in the inputarray as the X-coordinate.
PS: The class keeps a reference to the inputarray (m_data variable) but that's ofcourse not needed, you only need it to initialize your points.
PS: My "Visualization" class which is extended by all visualizations, is basicly a JPanel.
PS: The code above is written for positive integers, so will probably need some extra coding to handle negative integers aswell ;).
Then to visualize the actions of the algorithm, I used the observer pattern. The algorithm, for example bubblesort, looked like this:
for(int i = 0; i < size(); ++i)
for(int j = 1; j < size(); ++j)
if(greaterThan(j - 1, j))
swap(j - 1, j);
Where the function swap was defined as follows (simplified version again):
protected void swap(int index1, int index2)
{
if(index1 != index2)
{
incrementSwap(); // counting swaps and visualizing counter
m_command.clear();
m_command.setAction(Action.SWAP);
m_command.addParameter(index1);
m_command.addParameter(index2);
setChanged();
notifyObservers(m_command);
E temp = m_data[index1];
m_data[index1] = m_data[index2];
m_data[index2] = temp;
}
}
Where I notified my observers (visualizations) that a swap occured on index1 and index2. The m_command variable is an instance of the Command-class (wrote it myself) which is just a wrapper for the information needed by the visualization. Which is: the action that occured and the relevant information (indices for a swap-action for example).
So in the visualization i swapped the GRectangles on those indices aswell as their X-coordinates;
private void swap(int index, int index2)
{
if(index == index2)
return;
GRectangle r1 = m_points.get(index);
GRectangle r2 = m_points.get(index2);
int tempX = r1.getX();
r1.setLocation(r2.getX(), r1.getY());
r2.setLocation(tempX, r2.getY());
m_points.set(index, r2);
m_points.set(index2, r1);
}
You can add lines like this:
try {
Thread.sleep(100);
} catch(InterruptedException ignore) {}
to let a thread sleep 100ms before continueing. This might come in handy if it's getting visualized too fast.
So for an array with random integers it might look like this:
And after sorting:
(Ofcourse it's not a straight line because the values in the inputarray were generated at random in this case)
So if you have to - like I had to - allow multiple algorithms to work with the same visualization, I can recommend you to separate the visualization class and the algorithm class and work with an observer pattern to let the visualization update whenever an action occurs (set, swap, ...).
And then you can create something like this for comparisons;
http://i445.photobucket.com/albums/qq179/ultddave/DotVisualizationMany_zps63269d2a.png
http://i445.photobucket.com/albums/qq179/ultddave/DotVisualizationMany2_zps65e96fa9.png
Good luck!

Related

What is a good and simple way to get state of neighbours in a 2d array in java for conway's game of life?

I am about to learn java right now (I came from C++), and I am trying myself in GUI-Programming.
My goal is to create a playable version of "conway's game of life" (which is a good beginner project i think).
What i have managed to do is, that i stored all of my cells in a 2d array (Here is my gode for that)
public class Panel extends JPanel
{
private int PanelX = 1777, PanelY = 1000;
public boolean[][] grid = new boolean[192][108];
public Panel()
{
this.setBackground(Color.black);
this.setSize(PanelX, PanelY);
this.setVisible(true);
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.green);
prepareGrid(); // sets the entire index of grid[][] to zero for start and reset
drawGrid(g2d); // draws the grid
}
private void prepareGrid()
{
for (int i = 0; i<191; i++)
{
for (int t = 0; t<107; t++)
{
grid[i][t] = false;
}
}
}
private void drawGrid(Graphics g)
{
for (int i=0; i<=191; i++)
{
for (int t=0; t<=107; t++)
{
if (grid[i][t] == false)
{
g.drawRect(i*10, t*10, 10, 10);
}
if(grid[i][t] == true)
{
g.fillRect(i*10, t*10, 10, 10);
}
}
}
}
}
So what it does it creates an 2 dimensional array which stores all cells as either false = no cell, or true = cell. When an array index (for example grid[100][100] is true, it draws a filled rectangle on that position as a "living cell".
To implement the game and the rules of the game now, I need a way to access all the neighbor positions of an index of that 2d array, but I do not know how to to that. Could anyone help me with that ? :)
-> And if you have major optimizations for my code, feel free to write them as well.
Adding to markspace's answer, it is important to ensure that the counting of alive cells does not interfere with their updating (letting cells be born or die) in the same generation. In other words: If you count 3 neighbors of a dead cell, you must not immediately set it to alive, because it must still be counted as dead for its other neighbors.
You could, for example, first count the neighbors for every cell and then, in a second nested loop, update every cell according to its previously counted number of neighbors. But you can do better with a more elaborate algorithm: you do not absolutely need an array of counters of the same size as your grid.
It's just counting, it's not really hard. Use two loops to count all eight adjacent cells, skip the middle one when you find that cell.
/**
* Returns the number of "cells" that are alive and adjacent to
* the cell at the given X,Y coordinates.
*
*/
public int aliveAdjacent( int x, int y ) {
int count = 0;
for( int xd = -1; xd <= 1; xd++ )
for( int yd = -1; yd <= 1; yd++ ) {
if( xd == 0 && yd == 0 ) continue;
if( isAlive( wrap(x+xd, width), wrap(y+yd,heigth) ) ) count++;
}
return count;
}

Recalculate X and Y Coordinates From New Screensize

I'm trying to display tiles from an array I have so that they always fill the size of the screen when drawn together. I am ignoring aspect ratio for now.
Here's how my code works. I have tile objects that are passed on to a tileset (class for managing an array of tile objects), and then I iterate through the tileset array, returning each tile object id and rendering a subimage of my tileset image based on said ids.
Here's my mapUpdate method, which is called on every JFrame resize event:
public synchronized void mapUpdate(Screen screen) {
factorX = (float)(screen.getWidth() / scW);
factorY = (float)(screen.getHeight() / scH);
for (int i = 0; i < tileset.getRows(); i++) {
for (int j = 0; j < tileset.getCols(); j++) {
int x = tileset.getTile(i, j).getX();
int y = tileset.getTile(i, j).getY();
tileset.getTile(i, j).setX((int)(x * factorX));
tileset.getTile(i, j).setY((int)(y * factorY));
}
}
mapTiles.clear();
for (int i = 0; i * 70 < mapImage.getWidth(); i++) {
mapTiles.add(mapImage.getSubimage(70 * i, 0, 70, 70).getScaledInstance(screen.getWidth() / 10, screen.getHeight() / 10, Image.SCALE_SMOOTH));
}
}
mapTiles is an ArrayList of Images, and on each resize event it resets the arraylist, scales my subimages to 1/10th width and height, and then re-adds the newly sized images for me to pull out for rendering (the tileset image is only 3 tiles with an original size of 70x70).
And here is the componentResized method if you were curious:
public void componentResized(ComponentEvent e) {
canvas.setSize(app.getContentPane().getWidth(), app.getContentPane().getHeight());
if (level1 != null) {
level1.mapUpdate(this);
}
}
As you can see in my mapUpdate method, I attempt to get a float to multiply each current x and y value by to receive the new correct values (it will round the integers), but this doesn't work at all.
Is there any solution to easily re-calculate my X and Y coordinates so that the tiles are drawn correctly?
Your factorX should not be a float. It should be an int. If you use a float you will get rounding, so occasionally you will have a pixel gap between tiles because of rounding. If you just use an int then you don't have to worry about this. Then the location is just the factor * the index value of the for loop.
On the other hand the easiest solution is to just use a JPanel with a GridLayout. Then you can add a JLabel with an Image icon. The GridLayout will resize each component equally.
You can then even use the Stretch Icon and the images will be dynamically resized as the frame is resized.
SOLUTION courtesy of #MadProgrammer - The solution was to simply calculate the new X and Y "origins" for each tile. I still need to implement adjusting the position for tiles that have moved based on the newly calculated origins, but this solution works for tiles that do not move (again, simply recalculate the X and Y origin positions).
public synchronized void mapUpdate(Screen screen) {
int originX = screen.getWidth() / 10;
int originY = screen.getHeight() / 10;
for (int i = 0; i < tileset.getRows(); i++) {
for (int j = 0; j < tileset.getCols(); j++) {
tileset.getTile(i, j).setX((originX * j));
tileset.getTile(i, j).setY((originY * i));
}
}
mapTiles.clear();
for (int i = 0; i * 70 < mapImage.getWidth(); i++) {
mapTiles.add(mapImage.getSubimage(70 * i, 0, 70, 70).getScaledInstance(screen.getWidth() / 10, screen.getHeight() / 10, Image.SCALE_SMOOTH));
}
}

Renderer/Sorting optimization

Okay here is the problem:
i do have a list of Objects that does need to be updated by the time since the last frame
the list need to be ordered by the y koordinate of the Object before they get draw
Current i do this with a collection.sort and a simple comperator:
figureComperator = new Comparator<Actor>() {
#Override
public int compare(Actor o1, Actor o2) {
return (int) o2.getY() - (int) o1.getY();
}
};
The render does look like this:
#Override
public void render(float delta) {
// clearing
Gdx.gl.glClearColor(0, 0, 0, 1f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// act the character act in front
this.character.myAct(delta);
updateGameCam();
if (this.status == GameStatus.GAME) {
// just monster act now
this.figureStage.act();
}
this.figureStage.getActors().sort(figureComperator); // sort figures
// render background
this.map.drawBackground(); // draw background
// draw figures inclusive character
this.figureStage.draw(); //draw all figures
this.map.drawForeground(); // foreground
// render game HUD and act gameHud
this.gameHud.act(delta);
this.gameHud.draw();
}
So i am looking for a better way to improve the speed of this.
I do came across the idea of let the actors sort itself inside of the list(figureStage) while i do update those. But as i do the update forall with the this.figureStage.act(); i couldnt do it that easy.
So my question is, if there is any solution without having the complexity of an sorting algorithm to always have those objects sorted by its position?
You can store your Objects in an array (or list) of HEIGHT elements in size, where HEIGHT is vertical size of your world. Each element in this list is a list of objects with the corresponding Y coordinate.
When an object moves up or down it should be removed from one list and added to another according to its new Y coordinate.
This way you can just iterate the array and draw all objects in inner lists.
If Y coordinate is not integer you can use integer part of it.
Hope this helps.
With the help of #Joni i started using a differend algorithm to sort the Actors. It does increased the sorting speed by around 2-3 Times just by using an insertionsort.
public void sortList(Array<Actor> array) {
// double starttime = System.nanoTime();
for (int i = 1; i < array.size; i++) {
Actor temp = array.get(i);
int j = i - 1;
while (j >= 0 && array.get(j).getY() < temp.getY()) {
array.set(j + 1, array.get(j));
j--;
}
array.set(j + 1, temp);
}
// System.out.println("Time taken: " + (System.nanoTime() - starttime));
}
Average ns of the Collection.sort was ~8700. Insertion is around 3300!

Animating Graphical Sort

I am working on an assignment called "Graphical Sort", which is basically animating sort algorithm graphically.
I just need help on animating the sorting process.
I tried using Thread, but the program hangs till the threading process is completed, then it shows the final result.
Below are the picture of how my program looks like:
Below is the class of the panel I use to paint on
import javax.swing.*;
import java.awt.*;
import java.util.*;
public class PaintPanel extends JPanel
{
// Create an array of 34 element size
int[] Arr = new int [34];
// Set default X pointer to 20
int x = 50;
// Declare Y pointer to 660
int y = 660;
// Set the length of array to n variable
int n = Arr.length;
/*
* main method
* #param none
* #return none
*/
public PaintPanel ()
{
randomNums ();
}
/*
* Generates random numbers between 50 and 750 and stores it into the Arr variable
* #param none
* #return none
*/
public void randomNums ()
{
// call randomGenerator object
Random randomGenerator = new Random ();
// Loop 33 times = Generates 33 random integers
for (int i = 0 ; i <= 33 ; ++i)
{
// Generate random Number
int randomInt = randomGenerator.nextInt (700);
// Conditional statement, if any number is less than 50, then discard it and generate new number
if (randomInt > 50)
// Assign each random number into Arr Element
Arr [i] = randomInt;
else
{
// Regenerate Random Number
randomInt = randomGenerator.nextInt (700);
// Assign it again
Arr [i] = randomInt;
}
}
}
/*
* Bubble Sort Algorithm
* #param none
* #return none
*/
public void bubble ()
{ //Pre: a is an array with values. It is of size n
//Post: the values in a are put in ascending order
int temp;
int a[] = Arr;
for (int i = 0 ; i < n - 1 ; i++)
{
for (int j = 0 ; j < n - 1 - i ; j++)
{ // compare the two neighbours
if (a [j + 1] < a [j])
{ //swap the neighbours if necessary
temp = a [j];
a [j] = a [j + 1];
a [j + 1] = temp;
}
}
}
}
/*
* Paints 33 rectangle Strips to the screen
* #param Graphics g
* #return none
*/
public void paintComponent (Graphics g)
{
super.paintComponent (g);
// Call Graphics2D Object
Graphics2D g2 = (Graphics2D) g.create ();
// Create Paint Object with gradient Fill
Paint p = new GradientPaint (
0, 0, new Color (0x44A2FF),
getWidth (), 0, new Color (0x0CBEAE),
true
);
// Set the gradient fill to the Graphics2D Object
g2.setPaint (p);
// Loop through the Array and display series of Rectangular Strips
for (int i = 0 ; i < Arr.length ; ++i)
{
// Fill out the Rectangle
g2.fillRect (x, y, Arr [i], 8);
y = y - 15;
}
g2.dispose ();
}
}
What should I use to animate the process. I also want to show which rectangular strips are being compared during the process of sorting.
Thank You
When I wrote a similar program, I created a SortListener interface with two methods: onCompare() and onSwap(). I used the onCompare() to highlite the two elements being compared with a different color and the onSwap() to notify the GUI to repaint istelf.
I also created a 'SortingAlgorithm' abstract class and several subclasses for specific sorting algorithms. The super class defined addSortListener() to allow other classes to register listeners. Then during the sorting algorithm, I called onCompare() immediately after a comparison and onSwap() imediately after two elements were swapped.
Finally, the JPanel where I did my painting implemented the SortListener interface and responded to onCompare() and onSwap() by repainting the animation.

How to flip an image horizontally with an ImageJ-Plugin?

I want to develop a Java-Plugin for ImageJ that flips an image horizontally.
But my code flips only half of the picture. Maybe, there is something wrong with the construction or the output of the image copy?
public class flipHorizontal implements PlugInFilter {
public int setup (String arg, ImagePlus imp)
{
return DOES_ALL;
}
public void run (ImageProcessor ip)
{
int height=ip.getHeight();
int width=ip.getWidth();
ImageProcessor copy = ip;
for (int x=0; x<width; x++) {
for (int y=0; y<height; y++) {
int p=ip.getPixel(width-x-1,y);
copy.putPixel(x,y,p);
}
}
}
}
Your logic is wrong. What you get is normal: you're not processing half of your image but flipping horizontally once half of your image and twice the other half (if I'm not mistaken).
Anyway, if you want to flip horizontally by manipulating pixels yourself directly, as in your code sample, then instead of going to width, you need to go to half the width (width/2).
You then need to actually invert the two pixels from "left" and "right"
Here's an horizontal flip that works:
for (int x = 0; x < w / 2; x++) {
for (int y = 0; y < h; y++) {
final int l = tmp.getRGB( w - (x + 1), y);
final int r = tmp.getRGB( x, y);
tmp.setRGB( x, y, l );
tmp.setRGB( w - (x + 1), y, r );
}
}
There may be "off-by-one" errors in the code above but you should get the idea.
TacticalCoder is correct that you should only be iterating to half way across the image, and you need to save the value from the other side before overwriting it.
There are two additional points that might be worth making, however - one is the the ImageProcessor class already has a method called flipHorizontal, so you can simplify your code to:
public class flipHorizontal implements PlugInFilter {
public int setup (String arg, ImagePlus imp) {
return DOES_ALL;
}
public void run (ImageProcessor ip) {
ip.flipHorizontal();
}
}
The other point that would be worth making is that it seems that you misunderstand what this line means:
ImageProcessor copy = ip;
That's just creating another reference to the same object as ip, so:
copy.putPixel(x,y,p);
... and:
ip.putPixel(x,y,p);
... have exactly the same effect. If you want to create a new ImageProcessor representing the same pixel data, you could do:
ImageProcessor copy = ip.duplicate();
However, that's not necessary in this case.

Categories