1.完全二叉树有两种:
5
/ \
1 2
/ \ /
3 4 2 6
满二叉树
5
/ \
1 2
/
1
从左到右排序的二叉树
2.完全二叉树可等价为堆,堆可用数组实现
其中第i结点的左孩子:2i+1,第i结点的右孩子:2i+2,第i结点的父节点:(i-1)/2
3.大根堆:指任意子树的最大值是其头部的结点
小根堆:指任意子树的最小值是其头部的结点
把数组变为大根堆,建立堆结构
如果当前插入的元素大于其父节点的元素,那么交换父节点与当前节点的位置。接着考察更换结点后的插入元素与新位置的父节点大小,如果还是大于还要继续交换。
eg。例[2,1,3,6]变换为大根堆
位置0,1,2,3
(1)2插入,父节点(0-1)/2 = 0位置,自己和自己不动;
(2)1插入,父节点(1-1)/2 = 0位置,1<2,不动;
(3)3插入,父节点(2-1)/2 = 0位置,3>2,交换位置;此时3的位置变为0,父节点(0-1)/2 = 0位置,自己和自己不动;
此时:
3
/
1 2
(4)6插入,父节点(3-1)/2 = 1位置,6>1,交换位置;此时6的位置变为1,父节点(1-1)/2 = 0位置;6>3,继续交换;
6
/
3 2
/
1
(index-1)/2是index父节点的位置
void heapinsert(int arr[],int index)
{
while(arr[index] > arr[(index-1)/2])
{
swap(arr[index],arr[(index-1)/2]);
index = (index-1)/2;
}
}
使用for循环遍历数组,调用heapinsert
for(int i = 0;i < length;i++ )
{
heapinsert(arr,i);//用for循环传入要处理的index
}
#include
#define length 5
using namespace std;
void swap(int &a,int &b)
{
int temp = a;
a = b;
b = temp;
}
void heapinsert(int arr[],int index)
{
while(arr[index] > arr[(index-1)/2])
{
swap(arr[index],arr[(index-1)/2]);
index = (index-1)/2;
}
}
int main()
{
//int arr[length] = {2,1,3,6,0,4};
int arr[length] = {
3,4,5,1,2};
int heapsize = length;
for(int i = 0;i < length;i++ )
{
heapinsert(arr,i);//用for循环传入要处理的index
}
system("pause");
return 0;
}
加一个数需要比较树的高度次,O(logN),当0到i-1加入一个数需要比较log(I-1)次;N个数需要log1+log2+…+log(N-1)=O(N)
1.找出这个数的左右孩子中的最大值,将这个最大值与改变的值进行比较,如果改变的值大于左右孩子的最大值,则交换两个数,接着找到交换后的左右孩子,继续比较。
2.继续比较的条件:左孩子未越界。
比较左右孩子和当前的数,找出最大值赋给largest;如果当前数是largest则跳出,如果不是,则交换两个数,更新index,和左孩子位置,继续比较。
void heapify(int arr[],int index,int heapsize)
{
int left = index * 2 + 1;
while(left < heapsize)
{
int largest = left + 1 < heapsize && arr[left]<arr[left + 1] ?
left + 1:left;
largest = arr[largest] > arr[index] ? largest : index;
if(largest == index)
break;
swap(arr[largest],arr[index]);
index = largest;
left = index * 2 + 1;
}
}
#include
#define length 6
using namespace std;
void swap(int &a,int &b)
{
int temp = a;
a = b;
b = temp;
}
void heapify(int arr[],int index,int heapsize)
{
int left = index * 2 + 1;
while(left < heapsize)
{
int largest = left + 1 < heapsize && arr[left]<arr[left + 1] ?
left + 1:left;
largest = arr[largest] > arr[index] ? largest : index;
if(largest == index)
break;
swap(arr[largest],arr[index]);
index = largest;
left = index * 2 + 1;
}
}
int main()
{
//int arr[length] = {2,1,3,6,0,4};
int arr[length] = {
6,5,4,3,5,2};
int heapsize = length;
arr[0] = 1;
heapify(arr,0,heapsize);
system("pause");
return 0;
}
heapinsert结合heapify。
(1)让数组变为大根堆(heapinsert);
(2)让最后一位和堆顶交换,堆大小减一(保存最大值)
(3)再重新变为大根堆,相当于把堆顶元素变小再重排(heapify)
(4)直到堆大小为1停止。
1.heapinsert
void heapinsert(int arr[],int index)
{
while(arr[index] > arr[(index-1)/2])
{
swap(arr[index],arr[(index-1)/2]);
index = (index-1)/2;
}
}
2.heapify
void heapify(int arr[],int index,int heapsize)
{
int left = 2*index+1;
while (left < heapsize)
{
int largest = left+1<heapsize && arr[left+1]>arr[left]?
left+1:left;
largest = arr[index] < arr[largest]?largest:index;
if(index == largest)
break;
swap(arr[index],arr[largest]);
index = largest;
left = 2*index+1;
}
}
3.heapsort
void heapsort(int arr[],int heapsize)
{
while(heapsize > 1)
{
swap(arr[0],arr[heapsize-1]);
heapsize--;
heapify(arr,0,heapsize);
}
}
#include
#include
#define length 10
using namespace std;
void swap(int &a,int &b)
{
int temp = a;
a = b;
b = temp;
}
void heapify(int arr[],int index,int heapsize)
{
int left = 2*index+1;
while (left < heapsize)
{
int largest = left+1<heapsize && arr[left+1]>arr[left]?
left+1:left;
largest = arr[index] < arr[largest]?largest:index;
if(index == largest)
break;
swap(arr[index],arr[largest]);
index = largest;
left = 2*index+1;
}
}
void heapsort(int arr[],int heapsize)
{
while(heapsize > 1)
{
swap(arr[0],arr[heapsize-1]);
heapsize--;
heapify(arr,0,heapsize);
}
}
void heapinsert(int arr[],int index)
{
while(arr[index] > arr[(index-1)/2])
{
swap(arr[index],arr[(index-1)/2]);
index = (index-1)/2;
}
}
int main()
{
srand((unsigned)time(NULL));
int arr[length] ;
int heapsize = length ;
cout<<"arr = ";
for(int i = 0;i<heapsize;i++)
{
arr[i] = rand()%10;
cout<<arr[i]<<" ";
heapinsert(arr,i);
}
cout<<endl<<"arr1 = ";
heapsort(arr,heapsize);
for(int i = 0;i<length;i++)
{
cout<<arr[i]<<" ";
}
cout<<endl;
//system("pause");
return 0;
}
O(N*logN),不考虑建立堆的过程,每次排序logN,排N个。