算法

排序算法

冒泡排序

  • 每次将一个值最大的数据沉底;
  • 下一个循环不用再比较已经沉底的值,因此j<n-i
  • 时间复杂度O(n²);
public class QiPao {
public static void main(String[] args) {
QiPao qiPao = new QiPao();
int [] data = {8, 10, -2, 7, 3, -5, 4};
qiPao.sort(data, data.length);
for (int i=0; i<data.length; i++) {
System.out.print(data[i]);
System.out.print(" ");
}
System.out.println();
}

public void sort(int [] data, int n) {
for (int i=0; i<n; i++) {
for (int j=1; j<n-i; j++) {
if (data[j-1] > data[j]) {
int temp = data[j-1];
data[j-1] = data[j];
data[j] = temp;
}
}
}
}
}

冒泡排序改进

  • 在最大数沉底过程中,如果一个循环都没有发生一次数据交互,也就是说本次循环时数据都已经是从小到大排列了,可以直接结束;
  • 第一个循环for (int i=0; i<n; i++) 变为 while(flag){ k-- }
  • flag=false 说明本次起泡过程中没有发生数据位置交换,数据已经排好序;
public class QiPao2 {
public static void main(String[] args) {
QiPao2 qiPao = new QiPao2();
int [] data = {8, 10, -2, 7, 3, -5, 4};
qiPao.sort(data, data.length);
for (int i=0; i<data.length; i++) {
System.out.print(data[i]);
System.out.print(" ");
}
System.out.println();
}

public void sort(int [] data, int n) {
boolean flag = true;
int k = n;
while(flag) {
flag = false;
for (int j=1; j<k; j++) {
if (data[j-1] > data[j]) {
int temp = data[j-1];
data[j-1] = data[j];
data[j] = temp;
flag = true;
}
}
k--;
}
}
}

常见算法

全排列(递归)

  • 最重要是要交换回来;
public class QuanPaiLie {
public static void main(String[] args) {
QuanPaiLie quanPaiLie = new QuanPaiLie();
char [] data = {'1', '2', '3', '4'};
quanPaiLie.queue(data, 0, data.length);
}

public void queue(char [] data, int from, int to) {
if (from == to) {
System.out.println(data);
return;
}

for (int i=from; i<to; i++) {
swap(data, i, from);
queue(data, from+1, to);
swap(data, from, i);
}
}

private void swap(char [] data, int from, int to) {
if (from != to) {
char temp = data[from];
data[from] = data[to];
data[to] = temp;
}
}
}

生产者消费者算法

wait/notify

  • wait()notify() 都必须在synchronized 代码块内;
  • wait() 需要做while() 判断,if() 判断不行,while() 可以防止虚假唤醒;如果出现虚假唤醒,while保证再判断一次,还可以继续wait
public class ProducerConsumer1 {

private List<Integer> list = new ArrayList<>();

private int max = 10;

private AtomicInteger count = new AtomicInteger(0);

public static void main(String[] args) {
ProducerConsumer1 producerConsumer = new ProducerConsumer1();
producerConsumer.start();
}

public void start() {
new Thread(new Producer()).start();
new Thread(new Consumer()).start();
}

public class Producer implements Runnable {

@Override
public void run() {
while (true) {
synchronized (list) {
while (list.size() >= max) {
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

int value = count.incrementAndGet();
list.add(value);
System.out.println("producer: " + value);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
list.notifyAll();
}
}
}
}

public class Consumer implements Runnable {

@Override
public void run() {
while(true) {
synchronized (list) {
while(list.size() == 0) {
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

int data = list.get(0);
list.remove(0);
System.out.println("consumer: " + data);

try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
list.notifyAll();
}
}
}
}
}

BlockingQueue

  • 使用ArrayBlockingQueue也可以实现生产者-消费者,代码要简单得多;
public class ProducerConsumer2 {

private BlockingQueue<Integer> list = new ArrayBlockingQueue<Integer>(10);

private AtomicInteger count = new AtomicInteger(0);

public static void main(String[] args) {
ProducerConsumer2 producerConsumer = new ProducerConsumer2();
producerConsumer.start();
}

public void start() {
new Thread(new Producer()).start();
new Thread(new Consumer()).start();
}

public class Producer implements Runnable {

@Override
public void run() {
while (true) {
int value = count.incrementAndGet();
try {
list.put(value);
System.out.println("producer: " + value);
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

public class Consumer implements Runnable {

@Override
public void run() {
while(true) {
try {
int data = list.take();
System.out.println("consumer: " + data);
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}

多生产者多消费者

  • 为了简化,以ArrayBlockingQueue实现为例;
  • 这里只想说明前面的代码,不限于只能是一个生产者和一个消费者;
  • 生产者和消费者代码除了在日志中增加了线程名称以外,没有其他改动;
public class ProducerConsumer3 {

private BlockingQueue<Integer> list = new ArrayBlockingQueue<Integer>(10);

private AtomicInteger count = new AtomicInteger(0);

public static void main(String[] args) {
ProducerConsumer3 producerConsumer = new ProducerConsumer3();
producerConsumer.start();
}

public void start() {
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i=0; i<5; i++) {
executorService.execute(new Producer());
}
for (int i=0; i<3; i++) {
executorService.execute(new Consumer());
}
}

public class Producer implements Runnable {

@Override
public void run() {
while (true) {
int value = count.incrementAndGet();
try {
list.put(value);
String threadName = Thread.currentThread().getName();
System.out.println(threadName + ":producer: " + value);
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

public class Consumer implements Runnable {

@Override
public void run() {
while(true) {
try {
int data = list.take();
String threadName = Thread.currentThread().getName();
System.out.println(threadName + ":consumer: " + data);
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}