Java-자료구조 4주차 Heap 4 - 4 ~ 6

김메로·2022년 8월 23일

4주차. 힙
4-4.TrickleUp 함수

  • 완전이진트리로 노드의 위치는
    -children: (2 x parent) + 1, (2 x parent) + 2
    -parent: floor((child - 1) / 2)
    로 모든 노드가 level 순서 정렬로 위치가 잡힌다.
    ex)

<코드>

int lastposition; // 어디까지 요소를 넣었는지 위치를 알려줌
E[] array = (E[]) new Object[size];// 원하는 만큼 크기의 객체인 배열 생성
public void add(E obj){
	array[++lastposition] = obj; // 노드 추가
	trickleup(lastposition); //  trickle up
}

public void swap(int from, int to){
	// 보통 from이 child, to가 parent
	E tmp = array[from]; // 
	array[from] = array[to]; // to가 from이 있는 곳으로 이동
	array[to] = tmp; // from이 to가 있는 곳으로 이동
}

public void trickleup(int position){
	if (position == 0) // root: position = 0
		return;
	int parent = (int) Math.floor((position-1)/2) // parent 위치 
	if(((Comparable<E>)array[position]).compareTo(array.parent)>0) {
    // 부모와 현재 노드의 값을 비교(child > parent)한 뒤 실행 
		swap(position, parent);
		trickleup(parent);
	}
}

생각해보기)-위 코드에서 lastposition 변수를 사용하는 이유는 무엇인가요?

답: 완전이진트리로 2개씩 꽉 찬 트리 구조이기 때문에 노드가 추가된다면 마지막 위치에 추가해서 사용한다

4-5.TrickleDown 함수

  • 노드의 위치는 tickle up일 때와 동일.
    -children: (2 x parent) + 1, (2 x parent) + 2
    -parent: floor((child - 1) / 2)

<코드>

public E remove(){
	E tmp = array[0];
	swap(0, lastposition--); // 루트(0)와 마지막 노드를 바꿔주고 lastposition을 줄여 배열에서 제거합니다.
	trickleDown(0);
	return tmp;
}
public void trickleDown(int parent){
	int left = 2*parent + 1;
	int right = 2*parent + 2;
	
    // 마지막에 왼쪽 자식이 클 때
	if (left==lastposition && (((Comparable<E>)array[parent]).compareTo(array[left])<0){
		swap(parent, left)
		return;
	}
	// 마지막에 오른쪽 자식이 클 때
	if (right==lastposition && (((Comparable<E>)array[parent]).compareTo(array[right])<0){
		swap(parent, right)
		return;
	}
	// 마지막에 부모가 클 때
	if (left >= lastposition || right >= lastposition)
		return;
	
    // 왼쪽 자식이 클 때
	if (array[left] > array[right] && array[parent] < array[left]) {
		swap(parent, left);
		trickleDown(left);
	}
    // 오른쪽 자식이 클 때
	else if (array[parent] < array[right]){
		swap(parent, right);
		trickleDown(right);
	}
}

생각해보기)-루트의 정보를 없애는 대신 swap 함수를 이용하여 제거하면 어떤 점이 좋나요?

답: 루트를 제거한 뒤, 마지막 위치에 놓인 수를 루트와 바꿔 연결하기 때문에 완전 이진 트리 구조가 유지된다

4-6.정렬

ex)
배열:

데이터를 추가할 때마다 루트를 제거한 뒤, 루트에 데이터를 추가해 Tickledown을 발동
과정:

결과:

  • 시간복잡도: O(nlogn)
    이유:두 수를 비교하여 하나를 고르는 방식으로 숫자를 골라내(두 방향 중 하나를 정한 방향으로 trickle down) 여기서는 총 n개의 숫자를 logn개의 숫자와 비교
  • 장점 - 하나의 배열에서 시작하여 정렬된 상태로 끝나기 때문에 데이터의 복사본을 만들 필요X ===> 다른 정렬 알고리즘과 다르게 메모리 소모X

코드-https://velog.io/@youswim96/%ED%9E%99-%EC%A0%95%EB%A0%ACHeap-sort-%EC%9E%90%EB%B0%94JAVA
에서 참고!

생각해보기)-힙 정렬 알고리즘 외의 정렬 방법에는 어떤 것이 있을까요?

profile
완벽보다는 완성을 목표로!

0개의 댓글