树、二叉树简介
如果知道父节点,则子节点的下标为2i+1,2i+2
如果知道子节点,则父节点的下标为(i-1)/2
二叉树遍历方法:
先序(根 左右)、中序(左 根 右)、后序(左右 根)
先序:78 56 43 2 23 4 34 1 15
中序:2 43 23 56 4 78 1 34 15
后序:2 23 43 4 56 1 15 34 78
#include<bits/stdc++.h>
using namespace std;
template <class T>
int len(T& arr){
return sizeof(arr)/sizeof(arr[0]);
}
class TreeAndArray{
public:void preOrder(vector<int> vec,int i){
if(i>=vec.size())
return;
cout<<vec[i]<<endl;
preOrder(vec,i*2+1);
preOrder(vec,i*2+2);
}
public:void inOrder(vector<int> vec,int i){
if(i>=vec.size())
return;
inOrder(vec,i*2+1);
cout<<vec[i]<<endl;
inOrder(vec,i*2+2);
}
public:void backOrder(vector<int> vec,int i){
if(i>=vec.size())
return;
backOrder(vec,i*2+1);
backOrder(vec,i*2+2);
cout<<vec[i]<<endl;
}
};
int main()
{
int arr[]={78,56,34,43,4,1,15,2,23};
vector<int> vec(arr,arr+len(arr));
TreeAndArray tree;
tree.preOrder(vec,0);
cout<<"==========="<<endl;
tree.inOrder(vec,0);
cout<<"==========="<<endl;
tree.backOrder(vec,0);
return 0;
}
堆的概念
- 二叉堆是完全二叉树或者是近似完全二叉树
- 二叉堆满足两个特性:
- 1.父节点的键值总是大于或等于(小于或等于)任何一个 子节点的键值
- 2.每个节点左子树和右子树都是一个二叉堆(都是最大堆或最小堆)
- 任意节点的值都大于其他子节点的值–大顶堆
- 任意节点的值都小于其他子节点的值–小顶堆
将数组堆化伪代码:(小顶堆)
MinHelp(A){
n=A.length;
for i from n/2-1down to 0{
MinHeapFixDown(A,i,n);
}
}
MinHeapFixDown(A,i,n){
//找到左右孩子
left = 2*i+1;
right = 2*i+2;
//考虑越界问题
if(left>=n){
return;
}
min = left;
if(right>=n){
min=left;
}else{//左右孩子都没越界
if(A[right]<A[left]){
min = right;
}
}
//min指向了左右孩子中较小的那个
//如果A[i]比两个孩子都要小,不用调整
if(A[i]<=A[min]){
return;
}
//否则,找到两个孩子中较小的,和i交换
swap(A[i],A[min]);
//小孩子那个位置的值发生了变化,i变更为小孩子那个位置,递归调整
MinHeapFixDown(A,min,n);
}
完整代码
#include<bits/stdc++.h>
using namespace std;
template <class T>
int len(T& arr){
return sizeof(arr)/sizeof(arr[0]);
}
void MinHeapFixDown(vector<int> &A,int i,int n){
//找到左右孩子
int left = 2*i+1;
int right = 2*i+2;
//考虑越界问题
if(left>=n){
return;
}
int min = left;
if(right>=n){
min=left;
}else{//左右孩子都没越界
if(A[right]<A[left]){
min = right;
}
}
//min指向了左右孩子中较小的那个
//如果A[i]比两个孩子都要小,不用调整
if(A[i]<=A[min]){
return;
}
//否则,找到两个孩子中较小的,和i交换
swap(A[i],A[min]);
//小孩子那个位置的值发生了变化,i变更为小孩子那个位置,递归调整
MinHeapFixDown(A,min,n);
}
void MinHelp(vector<int> &A){
int n=A.size();
for(int i=n/2-1;i>=0;i--){
MinHeapFixDown(A,i,n);
}
}
int main()
{
int arr[]={5,1,3,6,10,11,2,4,10,12};
vector<int> vec(arr,arr+len(arr));
MinHelp(vec);
for(int i=0;i<vec.size();i++){
cout<<vec[i]<<endl;
}
return 0;
}
堆排序(小顶堆)
#include<bits/stdc++.h>
using namespace std;
template <class T>
int len(T& arr){
return sizeof(arr)/sizeof(arr[0]);
}
void MinHeapFixDown(vector<int> &A,int i,int n){
//找到左右孩子
int left = 2*i+1;
int right = 2*i+2;
//考虑越界问题
if(left>=n){
return;
}
int min = left;
if(right>=n){
min=left;
}else{//左右孩子都没越界
if(A[right]<A[left]){
min = right;
}
}
//min指向了左右孩子中较小的那个
//如果A[i]比两个孩子都要小,不用调整
if(A[i]<=A[min]){
return;
}
//否则,找到两个孩子中较小的,和i交换
swap(A[i],A[min]);
//小孩子那个位置的值发生了变化,i变更为小孩子那个位置,递归调整
MinHeapFixDown(A,min,n);
}
void MinHeap(vector<int> &A,int n){
for(int i=n/2-1;i>=0;i--){
MinHeapFixDown(A,i,n);
}
}
void sort(vector<int> &A,int n){
//先对A进行堆化
MinHeap(A,n);
for(int i=0;i<A.size();i++){
cout<<A[i]<<endl;
}
cout<<"===="<<endl;
for(int i=n-1;i>0;i--)
{
//把堆顶,0号元素和最后一个元素对调
swap(A[0],A[i]);
//缩小堆的范围,对堆顶元素进行向下调整
MinHeap(A,i);
}
}
int main()
{
int arr[]={5,1,3,6,10,11,2,4,10,12};
vector<int> vec(arr,arr+len(arr));
sort(vec,vec.size());
for(int i=0;i<vec.size();i++){
cout<<vec[i]<<endl;
}
return 0;
}
附:大顶堆
void MaxHeapFixDown(vector<int> &A,int i,int n){
//找到左右孩子
int left=2*i+1;
int right=2*i+2;
//看是否越界
if(left>=n){
return;
}
int max=left;
if(right>=n){
max=left;
}else{
if(A[right]>A[left])
max=right;
}
//看根节点是否大于子节点
if(A[i]>A[max]){
return;
}else{
swap(A[i],A[max]);
}
MaxHeapFixDown(A,max,n);
}
void MaxHeap(vector<int> &A,int n){
for(int i=n/2-1;i>=0;i--){
MaxHeapFixDown(A,i,n);
}
}
计数排序
- 一句话:用辅助数组对数组中出现的数字计数,元素转下标,小标转元素
- 假设元素均大于等于0,一次扫描原数组,将元素值k记录在辅助数组的k位上
- 一次扫描辅助数组,如果为1,将其插入目标数组的空白处
问题:
- 有负数
- 数据范围很大,比较稀疏,会导致辅助空间很大,造成空间浪费
数据范围较小或数据较密集适用
代码:
#include<bits/stdc++.h>
using namespace std;
template <class T>
int len(T& arr){
return sizeof(arr)/sizeof(arr[0]);
}
void CountSort(vector<int> &A){
int max = *max_element(A.begin(), A.end());
vector<int> helper(max+1,0);
for(int i=0;i<A.size();i++){
helper[A[i]]++;
}
int current=0;
for(int i=1;i<max+1;i++){
while(helper[i]>0){
A[current++]=i;
helper[i]--;
}
}
}
int main()
{
int arr[]={4,1,6,3,5,10,11,6,7};
vector<int> vec(arr,arr+len(arr));
CountSort(vec);
for(int i=0;i<vec.size();i++){
cout<<vec[i]<<endl;
}
return 0;
}