public int gcd(int a, int b){
return b == 0? a : gcd(b, a%b);
}
public int find(int x, int[] pre){
int r = x;
while(pre[r] != r){
r = pre[r];
//路径压缩,把x到根节点之间的点的上层节点直接改为根节点
int i=x, j;
while(i != r){
j = pre[i];
pre[i] = r;
i = j;
}
return r;
}
public void join(int x, int y){
//连通分支 合并
int fx = find(x);
int fy = find(y);
if(fx != fy)
pre[fx] = fy;
}
int ans = 0;
for(int i=0; i<n; i++){
ans = ans ^ num[i];
}
return ans;
public void bubble(int[] num){
for(int i=0; i<num.length; i++){
for(int j=0; j<num.length-i-1; j++){
//这里-i主要是每一次遍历,都把最大的i个数沉到最底下去了,没必要再替换了
if( num[j] > num[j+1){
int tmp = num[j];
num[j] = num[j+1];
num[j+1] = tmp;
}
}
}
public int partition(int[] data, int low, int high){
int key = data[low];
while( low < high){
while(low < high && data[high] > key)
high -- ;
data[low] = data[high];
while( low < high && data[low] < key)
low ++;
data[high] = data[low];
}
data[low] = key;
return low;
}
public void quicksort(int[] data, int low, int high){
int q ;
if( low < high){
q = partition(data, low, high);
quicksort(data,low,q-1);
quicksort(data,q+1,high);
}
}
首先讨论第二个问题:输出堆顶元素后,对剩余n-1元素重新建成堆的调整过程。
调整小顶堆的方法:
1)设有m 个元素的堆,输出堆顶元素后,剩下m-1 个元素。将堆底元素送入堆顶((最后一个元素与堆顶进行交换),堆被破坏,其原因仅是根结点不满足堆的性质。
2)将根结点与左、右子树中较小元素的进行交换。
3)若与左子树交换:如果左子树堆被破坏,即左子树的根结点不满足堆的性质,则重复方法 (2).
4)若与右子树交换,如果右子树堆被破坏,即右子树的根结点不满足堆的性质。则重复方法 (2).
5)继续对不满足堆性质的子树进行上述交换操作,直到叶子结点,堆被建成。
称这个自根结点到叶子结点的调整过程为筛选。
再讨论对n 个元素初始建堆的过程。
建堆方法:对初始序列建堆的过程,就是一个反复进行筛选的过程。
1)n 个结点的完全二叉树,则最后一个结点是第个结点的子树。
2)筛选从第个结点为根的子树开始,该子树成为堆。
3)之后向前依次对各结点为根的子树进行筛选,使之成为堆,直到根结点。
/**
* 已知H[s…m]除了H[s] 外均满足堆的定义
* 调整H[s],使其成为大顶堆.即将对第s个结点为根的子树筛选,
*
* @param H是待调整的堆数组
* @param s是待调整的数组元素的位置
* @param length是数组的长度
*
*/
static void HeapAdjust(int H[],int s, int length)
{
int tmp = H[s];
int child = 2*s+1; //左孩子结点的位置。(i+1 为当前调整结点的右孩子结点的位置)
while (child < length) {
if(child+1 <length && H[child]>H[child+1]) { // 如果右孩子小于左孩子(找到比当前待调整结点小的孩子结点)
++child ;
}
if(H[s]>H[child]) { // 如果较大的子结点小于父结点
H[s] = H[child]; // 那么把较小的子结点往上移动,替换它的父结点
s = child; // 重新设置s ,即待调整的下一个结点的位置
child = 2*s+1;
} else { // 如果当前待调整结点小于它的左右孩子,则不需要调整,直接退出
break;
}
H[s] = tmp; // 当前待调整的结点放到比其小的孩子结点位置上
}
}
/**
* 初始堆进行调整
* 将H[0..length-1]建成堆
* 调整完之后第一个元素是序列的最小的元素
*/
static void BuildingHeap(int H[], int length)
{
//最后一个有孩子的节点的位置 i= (length -1) / 2
for (int i = (length -1) / 2 ; i >= 0; --i)
HeapAdjust(H,i,length);
}
/**
* 堆排序算法
*/
static void HeapSort(int H[],int length)
{
//初始堆
BuildingHeap(H, length);
//从最后一个元素开始对序列进行调整
for (int i = length - 1; i > 0; --i)
{
//交换堆顶元素H[0]和堆中最后一个元素
int temp = H[i]; H[i] = H[0]; H[0] = temp;
//每次交换堆顶元素和堆中最后一个元素之后,都要对堆进行调整
HeapAdjust(H,0,i);
}
}
public static void main(String[] args) {
int[] H = {3,1,5,7,2,4,9,6,10,8};
HeapSort(H,10);
}
int depth = 0;
public void DFS(TreeNode root , int d){
if(root.left = null && root.rigth == null){
if(d > depth) depth = d;
else{
if(root.left != null)
DFS(root.left, d+1);
if(root.right != null)
DFS(root.right, d+1);
}
}
public void backtrace(int t){
if(t > n)
output(x); //叶子节点,输出结果,x是可行解
else{
for i = 1 to k {//当前结点的所有节点
x[t] = value(i); //每个子节点的值赋值给x
if( constraint(t) && bound(t))
backtrace( t+1);
}
}
}
public void iterativeBacktrace(){
int t = 1;
while( t> 0){
if( ExistSubNode(t)){ //当前节点存在子节点
for i = 1 to k {
x[t] = value(i);
if( constraint(t) && bound(t)){
if( solution(t)) output(x);
else t++;
}
}
}else
t--;
}
}