27
2018
08

堆排序

(二叉)堆是一个数组。它可以看成一个近似的完全二叉树,树上的每一个节点对应数组中的一个元素。除了最底层外,该树是完全充满的,而且是从左向右填充。表示堆得数组A包括两个属性,A.length给出数组元素的个数,A.heapSize表示有多少个堆元素存储在该数组中。

最大堆:父节点的值大于等于子节点的值。

最小堆:父节点的值小于等于子节点的值。

  • MAX_HEAPIFY过程:时间复杂度是O(lgn),它是维护堆性质的关键。

  • BUILD-MAX_HEAP过程:线性时间复杂度,功能是从无序的输入数据数组中构造一个最大堆。

  • HEAP-SORT过程:时间复杂度是O(nlgn),功能是对一个数组进行原址排序

  • MAX_HEAP_INSERT,HEAP-EXTRACT-MAX,HEAP-INCRESE_KEY,HEAP-MAXIMUM过程:时间复杂度O(lgn),功能是利用堆实现一个优先队列。

具体实现代码(最大堆):

var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
a.sort(function(){return Math.random()>0.5});
a.heapSize = a.length;

console.log(a.join('\t'));
//buildMaxHeap(a);
heapSort(a);
console.log(a.join('\t'));


function heapSort(a){
	buildMaxHeap(a);
	for(var i = a.length-1; i>0;i--){
		exchange(a, 0, i);
		a.heapSize--;
		maxHeapify(a, 0);
	}
}

function heapMaximum(a){
	return a[0];
}

function heapExtractMax(a){
	if(a.heapSize<0){
		throw(new Error('heap underflow'));
	}
	max = a[0];
	a[0] = a[a.heapSize - 1];
	a.heapSize--;
	maxHeapify(a, 0);
	return max;
}

function heapIncreaseKey(a, i, key){
	if(key < a[i]){
		throw(new Error('new key is smaller then current key'));
	}
	a[i] = key;
	var pi;
	while(i>0){
		pi = parent(i);
		if(a[pi] < a[i]){
			exchange(a, i, pi);
			i = pi;
		} else {
			break;
		}
	}
}

function maxHeapInsert(a, key){
	a[a.heapSize] = -Infinity;
	a.heapSize++;
	heapIncreaseKey(a, a.heapSize - 1, key);
}

function buildMaxHeap(a){
	for(var i = a.length>>1; i>=0;i--){
		maxHeapify(a, i);
	}
}

function buildMaxHeap2(a){
	a.heapSize = 1;
	for(var i = 1; i < a.length; i++){
		maxHeapInsert(a, a[i]);
	}
}

function heapDelete(a, i){
	a.heapSize--;
	a[i] = a[a.heapSize];
	maxHeapify(a, i);
	a[a.heapSize] = null;
}

function maxHeapify(a, i){
	var l = left(i);
	var r = right(i);
	var largest;
	if(l<a.heapSize && a[l]>a[i]){
		largest = l;
	} else {
		largest = i;
	}
	if(r<a.heapSize && a[r]>a[largest]){
		largest = r;
	}
	if(largest!=i){
		exchange(a,i,largest);
		maxHeapify(a,largest);
	}
}

function exchange(a,i,largest){
	var temp = a[i];
	a[i] = a[largest];
	a[largest] = temp;
}

function left(i){
	return i<<1 | 0x1;
}
function right(i){
	return (i<<1) + 2;
}

function parent(i){
	return (i-1)>>1;
}

/*function left(i){
	return i<<1;
}

function right(i){
	return i<<1 | 0x1;
}

function parent(i){
	return i>>1;
}*/

最小堆实现代码:

var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
a.sort(function(){return Math.random()>0.5});
a.heapSize = a.length;

console.log(a.join('\t'));
//buildMaxHeap(a);
//heapSort(a);
console.log(a.join('\t'));


function heapSort(a){
	buildMinHeap(a);
	for(var i = a.length-1; i>0;i--){
		exchange(a, 0, i);
		a.heapSize--;
		minHeapify(a, 0);
	}
}

function heapMinimum(a){
	return a[0];
}

function heapExtractMin(a){
	if(a.heapSize<0){
		throw(new Error('heap underflow'));
	}
	min = a[0];
	a[0] = a[a.heapSize - 1];
	a.heapSize--;
	minHeapify(a, 0);
	return min;
}

function heapIncreaseKey(a, i, key){
	if(key > a[i]){
		throw(new Error('new key is bigger then current key'));
	}
	a[i] = key;
	var pi;
	while(i>0){
		pi = parent(i);
		if(a[pi] > a[i]){
			exchange(a, i, pi);
			i = pi;
		} else {
			break;
		}
	}
}

function minHeapInsert(a, key){
	a[a.heapSize] = Infinity;
	a.heapSize++;
	heapIncreaseKey(a, a.heapSize - 1, key);
}

function buildMinHeap(a){
	for(var i = a.length>>1; i>=0;i--){
		minHeapify(a, i);
	}
}

function buildMinHeap2(a){
	a.heapSize = 1;
	for(var i = 1; i < a.length; i++){
		minHeapInsert(a, a[i]);
	}
}

function heapDelete(a, i){
	a.heapSize--;
	a[i] = a[a.heapSize];
	minHeapify(a, i);
	a[a.heapSize] = null;
}

function minHeapify(a, i){
	var l = left(i);
	var r = right(i);
	var least;
	if(l<a.heapSize && a[l]<a[i]){
		least = l;
	} else {
		least = i;
	}
	if(r<a.heapSize && a[r]<a[least]){
		least = r;
	}
	if(least!=i){
		exchange(a,i,least);
		minHeapify(a,least);
	}
}

function exchange(a,i,least){
	var temp = a[i];
	a[i] = a[least];
	a[least] = temp;
}

function left(i){
	return i<<1 | 0x1;
}
function right(i){
	return (i<<1) + 2;
}

function parent(i){
	return (i-1)>>1;
}

/*function left(i){
	return i<<1;
}

function right(i){
	return i<<1 | 0x1;
}

function parent(i){
	return i>>1;
}*/

https://github.com/hanyeah/lianxi/tree/master/算法导论/6


« 上一篇下一篇 »

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。