좌경 더미 (효율 적 인 합병 이 가능 한 우선 대기 열)

좌경 더미 (Left ist Heap) 는 merge 작업 에 편리 한 데이터 구조 로 좌경 수 (Left ist Tree) 를 통 해 이 루어 집 니 다.좌경 수 는 특수 한 이 진 트 리 이다. 나무의 결점 은 보통 이 진 트 리 의 key 크기 규정 을 만족 시 키 는 동시에 모든 결점 X 의 왼쪽 자나무 의 Null Path Length (NPL) 값 이 오른쪽 자나무 의 NPL 값 보다 작 지 않 기 때문에 이것 도 일반 이 진 트 리 와 차이 가 있다. 비록 이 진 트 리 도 좌경 수 조건 을 만족 시 키 지만 좌경 수 는 완전한 이 진 트 리 가 아니다.(그리고 일반적으로 불 균형) 좌경 수 는 배열 로 표시 할 수 없습니다. 위 에서 언급 한 NPL 은 어떤 결점 에서 NULL 결점 (총 n + 1 개의 NULL 결점) 을 말 합 니 다.의 최 단 경로 길이, 규정 NULL 결점 자체 의 NPL 은 - 1, 잎 결점 의 NPL 은 0, 비 잎 결점 의 NPL 은 두 아이 결점 의 NPL 최소 값 에 1 을 추가 합 니 다. 좌경 수 정의 에 따 르 면 좌우 자 수 는 모두 좌경 수 이 며 중요 한 속성 이 있 습 니 다. n 개의 결점 을 가 진 좌경 로 의 가장 오른쪽 경로 길이 (즉 루트 나 나무의 NPL 값 에 해당)최대 floor (log (n + 1) 로 이 특성 을 이용 하여 오른쪽 에서 아래 의 merge 작업 을 효과적으로 실현 할 수 있 습 니 다.
일반적인 이 진 더미 의 합병 복잡 도 는 O (n) 이 고 좌경 더미 의 합병 복잡 도 는 O (logn) 에 불과 하 다.(그렇지 않 으 면 h1 과 h2 를 교환 합 니 다) h2 의 뿌리 를 합 친 루트 노드 로 하고 merge (h1. root, h2. root. right) 를 재 귀적 으로 호출 합 니 다. 돌아 온 결 과 는 h2. root 의 오른쪽 서브 트 리 입 니 다. merge 작업 으로 돌아 온 트 리 가 왼쪽 경사 트 리 조건 을 만족 시 킬 수 있 기 때문에 돌아 온 결과 (지금 은 h2. root 의 오른쪽 서브 트 리 입 니 다)이미 왼쪽 나무 입 니 다. h2. root. right 의 NPL 값 이 h2. root. left 의 NPL 값 보다 크 면 두 개의 하위 나무 h2. root. left 와 h2. root. right 를 교환 하고 마지막 으로 h2. root 의 NPL 을 업데이트 해 야 합 니 다.
왼쪽 에 있 는 Extract - Min 작업 은 루트 노드 를 삭제 한 다음 merge 작업 을 통 해 좌우 트 리 를 새로운 왼쪽 트 리 로 합 칩 니 다. Insert 작업 은 삽입 할 요 소 를 루트 노드 만 포함 하 는 왼쪽 경사 로 보고 merge 작업 을 통 해 두 개의 왼쪽 경사 로 를 합 칩 니 다.
구조 좌경 로: Insert 작업 을 한다 면 복잡 도 는 O (nlogn) 이 고, 일반 이차 로 의 구조 방법 을 사용한다 면 복잡 도 는 O (n) 이다. 그러나 이것 은 가장 좋 은 좌경 로 가 아니다. 왜냐하면 한편 으로 는 구조의 좌경 로 가 완전 이차 수 이지 만 다른 한편 으로 는 수조 에 따라 조작 할 수 없 기 때문이다. FIFO 대기 열 구 조 를 사용 하면 O (n) 에 도달 할 수 있다.복잡 도, 동시에 구 조 된 좌경 적 좌경 적 효과 가 가장 좋다. 방법 은 다음 과 같다. 각 원 소 를 좌경 적 으로 한다 (두 원소 의 값 이 같 도록 허용 한다)순서대로 enqueue 를 한 다음 에 매번 대열 에서 dequeue 두 개의 좌경 더 미 를 merge 알고리즘 으로 합병 하고 합 병 된 좌경 더 미 를 팀 의 끝 에 놓 습 니 다. 대열 에 좌경 더 미 를 하나 남 길 때 까지 이 좌경 더 미 는 최종 결과 입 니 다.
실현:
import java.util.LinkedList;

 
/**
 * 
 * Leftist Heap   
 *  
 * Copyright (c) 2011 ljs (http://blog.csdn.net/ljsspace/)
 * Licensed under GPL (http://www.opensource.org/licenses/gpl-license.php) 
 * 
 * @author ljs
 * 2011-08-20
 *
 */
public class LeftistMinHeap {
	static class LeftistHeapNode{
		int key;
		LeftistHeapNode left;
		LeftistHeapNode right;
		int npl; //null-path-length
		
		public LeftistHeapNode(int key){
			this.key = key;
			this.npl = 0;
		}
		
		public String toString(){
			return this.key + "(npl=" + this.npl + ")";
		}
		
		public LeftistHeapNode merge(LeftistHeapNode rhsRoot){
			if(rhsRoot==this || rhsRoot == null) return this;
										
			LeftistHeapNode root1 = null; //the root of the merged tree
			LeftistHeapNode root2 = null; 
			if(rhsRoot.key<this.key){
				//merge this with rhsRoot's right child
				root1 = rhsRoot;
				root2 = this;
			}else{
				//merge rhsRoot with this's right child
				root1 = this;
				root2 = rhsRoot;				
			}
			
			LeftistHeapNode tmpRoot = root2.merge(root1.right);
			root1.right = tmpRoot;
			if(root1.left == null){ //left can not be null unless right is null
				root1.right = null;
				root1.left = tmpRoot;
				root1.npl = 0;
			}else{
				if(root1.right.npl>root1.left.npl){
					//swap left and right child						
					root1.right = root1.left;
					root1.left = tmpRoot;					
				}
				//at this time, the right child has the shortest null-path
				root1.npl = root1.right.npl + 1;
			}
			
			return root1;
		}
	}
	
	private LeftistHeapNode root;
	
	public LeftistMinHeap(LeftistHeapNode root){
		this.root = root;
	}
	
	private static LeftistHeapNode merge(LeftistHeapNode root1,LeftistHeapNode root2){
  		if(root1 == null) return root2;
		if(root2 == null) return root1;
		return root1.merge(root2); 
	}      
	public static LeftistMinHeap merge(LeftistMinHeap h1,LeftistMinHeap h2){
		LeftistHeapNode rootNode = merge(h1.root,h2.root);
		return new LeftistMinHeap(rootNode);
	}      
	
	public static LeftistMinHeap buildHeap(int[] A){
		LinkedList<LeftistHeapNode> queue = new LinkedList<LeftistHeapNode>();
		int n = A.length;
		//init: queue all elements as a single-node tree
		for(int i=0;i<n;i++){
			LeftistHeapNode node = new LeftistHeapNode(A[i]);
			queue.add(node);
		}
		//merge adjacent heaps and enqueue the merged heap afterward
		while(queue.size()>1){
			LeftistHeapNode root1 = queue.remove(); //dequeue
			LeftistHeapNode root2 = queue.remove();
			LeftistHeapNode rootNode = merge(root1,root2);
			queue.add(rootNode);
		}
		LeftistHeapNode rootNode = queue.remove();
		return new LeftistMinHeap(rootNode);
	}
	public void insert(int x){
		this.root = LeftistMinHeap.merge(new LeftistHeapNode(x), this.root);
	}
	
	public Integer extractMin(){
		if(this.root == null) return null;
		
		int min = this.root.key;
		this.root = LeftistMinHeap.merge(this.root.left, this.root.right);
		return min;
	}
	 
	public static void main(String[] args) {
		 int[] A = new int[]{4,8,10,9,1,3,5,6,11};
		 
		 LeftistMinHeap heap = LeftistMinHeap.buildHeap(A);
		 heap.insert(7);
		 Integer min = null;
		 while((min = heap.extractMin()) != null){
			 System.out.format(" %d", min);
		 }
		 System.out.println();
		 
		 System.out.println("********************");
		 A = new int[]{3,10,8,21,14,17,23,26};
		 
		 
		 LeftistHeapNode a0 = new LeftistHeapNode(A[0]);
		 LeftistHeapNode a1 = new LeftistHeapNode(A[1]);
		 LeftistHeapNode a2 = new LeftistHeapNode(A[2]);
		 LeftistHeapNode a3 = new LeftistHeapNode(A[3]);
		 LeftistHeapNode a4 = new LeftistHeapNode(A[4]);
		 LeftistHeapNode a5 = new LeftistHeapNode(A[5]);
		 LeftistHeapNode a6 = new LeftistHeapNode(A[6]);
		 LeftistHeapNode a7 = new LeftistHeapNode(A[7]);		 
		 a0.left = a1;  a0.npl = 1;
		 a0.right = a2; 
		 a1.left = a3;  a1.npl = 1;
		 a1.right = a4;
		 a4.left = a6;
		 a2.left = a5;
		 a5.left = a7;
		 LeftistMinHeap h1 = new LeftistMinHeap(a0);
		 
		 int[] B = new int[]{6,12,7,18,24,37,18,33};
		 LeftistHeapNode b0 = new LeftistHeapNode(B[0]);
		 LeftistHeapNode b1 = new LeftistHeapNode(B[1]);
		 LeftistHeapNode b2 = new LeftistHeapNode(B[2]);
		 LeftistHeapNode b3 = new LeftistHeapNode(B[3]);
		 LeftistHeapNode b4 = new LeftistHeapNode(B[4]);
		 LeftistHeapNode b5 = new LeftistHeapNode(B[5]);
		 LeftistHeapNode b6 = new LeftistHeapNode(B[6]);
		 LeftistHeapNode b7 = new LeftistHeapNode(B[7]);
		 b0.left = b1;  b0.npl = 2;
		 b0.right = b2;
		 b1.left = b3;  b1.npl = 1;
		 b1.right = b4; 
		 b4.left = b7;
		 b2.left = b5;  b2.npl = 1;
		 b2.right = b6;
		 LeftistMinHeap h2 = new LeftistMinHeap(b0);
		 
		 heap = LeftistMinHeap.merge(h1,h2);
		 while((min = heap.extractMin()) != null){
			 System.out.format(" %d", min);
		 }
		 System.out.println(); 
		 
		 System.out.println("********************");
		 A = new int[]{1,5,7,10,15,20,25,50,99};
		 a0 = new LeftistHeapNode(A[0]);
		 a1 = new LeftistHeapNode(A[1]);
		 a2 = new LeftistHeapNode(A[2]);
		 a3 = new LeftistHeapNode(A[3]);
		 a4 = new LeftistHeapNode(A[4]);
		 a5 = new LeftistHeapNode(A[5]);
		 a6 = new LeftistHeapNode(A[6]);
		 a7 = new LeftistHeapNode(A[7]);
		 LeftistHeapNode a8 = new LeftistHeapNode(A[8]);	
		 a0.left = a1; a0.npl = 2;		 
		 a0.right = a2;
		 a1.left = a3;  a1.npl = 1;
		 a1.right = a4;
		 a2.left = a5;  a2.npl = 1;
		 a2.right = a6;
		 a5.left = a7;  a5.npl =  1;
		 a5.right = a8;
		 h1 = new LeftistMinHeap(a0);
		 
		 B = new int[]{22,75};
		 b0 = new LeftistHeapNode(B[0]);
		 b1 = new LeftistHeapNode(B[1]);
		 b0.left = b1;
		 h2 = new LeftistMinHeap(b0);
		 
		 heap = LeftistMinHeap.merge(h1,h2); 
		 while((min = heap.extractMin()) != null){
			 System.out.format(" %d", min);
		 }
		 System.out.println();
	}

}

테스트 출력:
 1 3 4 5 6 7 8 9 10 11
********************
 3 6 7 8 10 12 14 17 18 18 21 23 24 26 33 37
********************
 1 5 7 10 15 20 22 25 50 75 99

좋은 웹페이지 즐겨찾기