多路文件归并,败者树算法

闲来无事,做了一个多路文件归并的工具,用败者树选择从多路输入中选择一个最小者,空间复杂度为O(K),K为归并输入的路数。该实现没有考虑最佳归并路径,等日后有空了再实现一个最佳归并路径的算法;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class MultiChannelMerge {
	
	public static class TNode {
		public int channel;
		public int value;
		public TNode(int c, int v) {
			channel = c;
			value = v;
		}
	}
	
	private int LEN = 0;
	private TNode[] loser;
	private int MAX = 0x7FFFFFFF;
	private int N = 0;
	private BufferedReader[] reader;
	
	public MultiChannelMerge(String[] files) throws FileNotFoundException {
		
		N = files.length;
		LEN = N + N -1;
		loser = new TNode[LEN];
		
		reader = new BufferedReader[N];
		try {
			// create buffered reader for each file
			for ( int i=0; i<N; i++ ) {
				reader[i] = new BufferedReader(new FileReader(files[i]));
			}
		} catch (FileNotFoundException e) {
			close();
			throw e;
		}

	}
	
	/*
	 * close all readers
	 */
	private void close() {
		// close buffered reader
		for ( int i=0; i<N; i++ ) {
			if ( reader[i] != null ) {
				try { reader[i].close(); } catch (IOException e1) {}
			}
		}
	}
	
	/*
	 * copy content of 'sour' node to 'dest' node
	 */
	private TNode cloneNode(TNode sour) {
		TNode dest = new TNode(sour.channel, sour.value);
		return dest;
	}
	
	/*
	 * feed a number from channel 'c' and get the winner
	 */
	public void feedTree(int c, TNode winner) throws IOException {
		
		String line = reader[c].readLine();
		
		winner.channel = c;
		winner.value = ( line != null ) ? Integer.valueOf(line) : MAX;
		
		int cur = N-1+c;
		do {
			cur = ( cur - 1 ) / 2;
			if ( loser[cur].value <= winner.value ) {
				swapNode(loser[cur],winner);
			}

		} while ( cur > 0 );
		
	}
	

	/*
	 * init a loser tree
	 */
	public void initTree(TNode res) throws IOException {
		
		TNode[] winner = new TNode[LEN];
		
		// read a number from each file
		for ( int c=0; c<N; c++ ) {
			String line = reader[c].readLine();
			int v = ( line != null ) ? Integer.valueOf(line) : MAX;
			TNode node = new TNode(c,v);
			winner[N-1+c] = node;
			loser[N-1+c] = node;
		}
		
		// calculate winner and loser for each node
		for ( int k=N-2; k>=0; k-- ) {
			
			int left = ( k << 1 ) + 1, right = ( k << 1 ) + 2;
			int win, los;
			
			if ( winner[left].value <= winner[right].value ) {
				win = left; los = right;
			} else {
				win = right; los = left;
			}
			
			winner[k] = cloneNode(winner[win]);
			loser[k] = cloneNode(winner[los]);

		}
		
		res.channel = winner[0].channel;
		res.value = winner[0].value;
		
	}
	
	/*
	 * multi-channel merge sort
	 */
	public void mergeSort() throws IOException {
		
		try {
			
			TNode winner = new TNode(0,MAX);
			initTree(winner);
			
			while ( winner.value != MAX ) {
				System.out.printf("%d ", winner.value);
				feedTree(winner.channel, winner);
			}
			
		} catch (IOException e) {
			close();
			throw e;
		}
		
	}

	/*
	 * swap the content of n1 and n2
	 */
	private void swapNode(TNode n1, TNode n2) {
		int temp_v = n1.value, temp_c = n1.channel;
		n1.value = n2.value; n1.channel = n2.channel;
		n2.value = temp_v; n2.channel = temp_c;
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		String[] file = {
				"c:\\temp\\a1.txt",
				"c:\\temp\\a2.txt",
				"c:\\temp\\a3.txt"
		};
		
		MultiChannelMerge instance = null;
		try {
			instance = new MultiChannelMerge(file);
			instance.mergeSort();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			instance.close();
		}
		
	}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值