堆
1.堆的概念
- 堆中某个结点的值总是不大于或不小于其父结点的值;
- 堆总是一棵完全二叉树
- 堆可以存储在顺序表中,假设父节点下标x,则它的左右孩子下标分别为2x+1、2x+2;若一个节点下标为x,则它的父节点为(x-1)/2
2.堆的实现
typedef int type;
typedef struct Heap
{
type* a;
int size;
int capacity;
}Heap;
void heap_init(Heap* hp)
{
assert(hp);
hp->a = NULL;
hp->size = hp->capacity = 0;
}
void heap_destroy(Heap* hp)
{
assert(hp);
free(hp->a);
hp->a = NULL;
hp->size = hp->capacity = 0;
}
//这是小根堆的up nlogn
void heap_small_up(type* a, int x)
{
int parent = (x - 1) / 2;
while (x > 0)
{
if (a[x] < a[parent])
{
heap_swap(&a[x], &a[parent]);
x = parent;
parent = (x - 1) / 2;
}
else
{
break;
}
}
}
//这是大根堆的up nlogn
void heap_big_up(type* a, int x)
{
int parent = (x - 1) / 2;
while (x > 0)
{
if (a[x] > a[parent])
{
heap_swap(&a[x], &a[parent]);
x = parent;
parent = (x - 1) / 2;
}
else
{
break;
}
}
}
void heap_push(Heap* hp, type x)
{
assert(hp);
if (hp->size == hp->capacity)
{
//需要扩容
int newcapa = (hp->capacity == 0) ? 4 : 2 * hp->capacity;
type* t = (type*)realloc(hp->a,sizeof(type) * newcapa);
if (t == NULL)
{
printf("realloc fail\n");
exit(-1);
}
hp->a = t;
hp->capacity = newcapa;
}
hp->a[hp->size] = x;
++hp->size;
heap_up(hp->a, hp->size - 1);//nlogn
}
void heap_print(Heap* hp)
{
assert(hp);
for (int i = 0; i < hp->size; ++i)
{
printf("%d ", hp->a[i]);
}
printf("\n");
}
void heap_swap(type* x, type* y)
{
type t = *x;
*x = *y;
*y = t;
}
type heap_top(Heap* hp)
{
assert(hp);
assert(hp->size > 0);
return hp->a[0];
}
void heap_pop(Heap* hp)//删除top元素
{
assert(hp);
assert(hp->size > 0);
heap_swap(&hp->a[0], &hp->a[hp->size - 1]);
hp->size--;
heap_down(hp->a,hp->size,0);//O(n)
}
bool is_empty(Heap* hp)
{
assert(hp);
return hp->size == 0;
}
int heap_size(Heap* hp)
{
assert(hp);
return hp->size;
}
//小根堆的下沉 T = n
void heap_down(type* a,int size, int x)
{
int child = 2 * x + 1;
while (child < size)
{
if (child+1 a[child])
{
child++;
}
if (a[child] > a[x])
{
heap_swap(&a[child], &a[x]);
x = child;
child = 2 * x + 1;
}
else
{
break;
}
}
}
void top_k(int *a, int k,int n)//在N中找最大或者最小的前k个,N>>k
{
//N100亿,40G内存才能放下
//eg.找最大的前k个,建立一个k的小堆
//步骤:1.前k个数建立一个小堆;2.剩下的N-k个数字里面,只要数字比堆顶要大,就进入堆;
int *kmin = (int*)malloc(sizeof(int)*k);
assert(kmin);
for(int i=0;i=0;--i)
{
heap_small_down(kmin, k, i);
}
for(int j = k; k>n; ++k)
{
if(a[j]>kmin[0])
{
kmin[0] = a[j];
heap_small_down(kmin, k, 0);
}
}
}
void heap_sort(type* a, int n)
{
//建堆1.O(nlogn)
for (int i = 1; i < n; ++i)
{
heap_small_up(a, i);
}
//建堆2.O(n)
int i = (n - 2) / 2;//最后一个结点的父亲,就是倒数第一个非叶子结点
for (; i >= 0; --i)
{
heap_small_down(a, n, i);
}
//要排升序,如果建立小堆,每次取完头,需要再次建堆。如果每次都是建堆来选数据,那太慢了!(n*n)没有使用到堆的优势
//所以升序建立大堆,降序建小堆,O(nlogn)
int end = n - 1;
while (end > 0)//nlogn
{
heap_swap(&a[0], &a[end]);
heap_down(a, end, 0);
--end;
}
}
3.链式存储的二叉树实现
typedef struct tree_node
{
struct tree_node* l;
struct tree_node* r;
type data;
}node;
node* buy_node(type x)
{
node* newnode = (node*)malloc(sizeof(node));
assert(newnode);
newnode->l = newnode->r = NULL;
newnode->data = x;
return newnode;
}
void pre_order(node* root)
{
if (root == NULL)
{
printf("$ ");
return;
}
printf("%d ", root->data);
pre_order(root->l);
pre_order(root->r);
}
void in_order(node* root)
{
if (root == NULL)
{
printf("$ ");
return;
}
pre_order(root->l);
printf("%d ", root->data);
pre_order(root->r);
}
void post_order(node* root)
{
if (root == NULL)
{
printf("$ ");
return;
}
pre_order(root->l);
pre_order(root->r);
printf("%d ", root->data);
}
//线程不安全
int count = 0;
void size1(node* root)
{
if (root == NULL)
{
return;
}
count++;
size1(root->l);
size1(root->r);
}
int size2(node* root)
{
if (root == NULL)
{
return 0;
}
return size2(root->l) + size2(root->r) + 1;
}
//求一棵树有多少叶子
int count1 = 0;
int lead_size1(node* root)
{
if (root == NULL)
return;
if (root->l == NULL && root->r == NULL)
count1++;
lead_size(root->l);
lead_size(root->r);
}
int lead_size2(node* root)
{
if (root == NULL)return 0;
if (root->l == NULL && root->r == NULL)
return 1;
return lead_size2(root->l) + lead_size2(root->r);
}
//求第k层结点的个数
int k_num(node* root,int k)
{
assert(k >= 1);
if (root == NULL)return 0;
if (k == 1)return 1;
return k_num(root->l, k - 1) + k_num(root->r, k - 1);
}
//求二叉树的深度
int deep(node* root)
{
if (root == NULL)return 0;
return deep(root->l) > deep(root->r) ? deep(root->l) + 1 : deep(root->r) + 1;
}
//求值为x的结点
node* find(node* root, type x)
{
if (root == NULL)
return NULL;
if (root->data == x)
return root;
node* ret1 = find(root->l, x);
if (ret1)return ret1;
node* ret2 = find(root->r, x);
if (ret2)return ret2;
return NULL;
}
//二叉树的层次遍历
void bfs(node* root)
{
queue q;
if(root!=NULL)q.push(root);
whlie(!q.empty)
{
node* t = q.top();
q.pop();
printf("%d ", t->data);
if (t->l != NULL)q.push(t->l);
if (t->r != NULL)q.push(t->r);
}
printf("\n");
}
void destroy(node* root)
{
//使用后序遍历
if (root == NULL)return;
destroy(root->l);
destroy(root->r);
free(root);
}
//判断一个二叉树是不是完全二叉树
bool is()
{
queue q;
if (root != NULL)q.push(root);
whlie(!q.empty())
{
node* t = q.top();
q.pop();
if (t)
{
q.push(t->l);
q.push(t->r);
}
else
{
break;
}
}
while (!q.empty())
{
node* t = q.top();
q.pop();
if (t)
{
q.destroy();
return false;
}
}
q.destroy();
return true;
}
4.链式存储的二叉树oj
//方法一
bool f = true;
void pre_order(struct TreeNode* root, int val)
{
if(root == NULL||f==false)return;
if(root->val != val)
{
f = false;
return;
}
pre_order(root->left, val);
pre_order(root->right,val);
}
bool isUnivalTree(struct TreeNode* root){
if(root==NULL)return true;
f = true;
pre_order(root,root->val);
if(f)return true;
return false;
}
//方法二
bool isUnivalTree(struct TreeNode* root){
if(root==NULL)return true;
if(root->left&&root->val != root->left->val)return false;
if(root->right&&root->right->val!=root->val)return false;
return isUnivalTree(root->left)&&isUnivalTree(root->right)
}
bool isSameTree(struct TreeNode* p, struct TreeNode* q){
if(p==NULL &&q==NULL)return true;
if(p==NULL ||q==NULL)return false;
if(p->val != q->val)return false;
return isSameTree(p->left,q->left)&&isSameTree(p->right,q->right);
}
bool is(struct TreeNode* p,struct TreeNode* q)
{
if(p==NULL &&q==NULL)return true;
if(p==NULL ||q==NULL)return false;
if(p->val != q->val)return false;
return is(p->left,q->right)&&is(p->right,q->left);
}
bool isSymmetric(struct TreeNode* root){
if(root == NULL)return true;
return is(root->left,root->right);
}
bool issame(struct TreeNode* p, struct TreeNode* q){
if(p==NULL &&q==NULL)return true;
if(p==NULL ||q==NULL)return false;
if(p->val != q->val)return false;
return issame(p->left,q->left)&&issame(p->right,q->right);
}
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){
if(root == NULL)return false;
if(issame(root, subRoot))return true;
return isSubtree(root->left,subRoot)||isSubtree(root->right,subRoot);
}
vectorans;
class Solution {
public:
void pre_order(TreeNode* root)
{
if(root== NULL)return;
ans.push_back(root->val);
pre_order(root->left);
pre_order(root->right);
}
vector preorderTraversal(TreeNode* root) {
ans.clear();
pre_order(root);
return ans;
}
};
typedef char type;
typedef struct tree_node
{
struct tree_node* l;
struct tree_node* r;
type data;
}node;
node* buy_node(type x)
{
node* newnode = (node*)malloc(sizeof(node));
assert(newnode);
newnode->l = newnode->r = NULL;
newnode->data = x;
return newnode;
}
node*create(char*str, int*pi)
{
if(str[*pi]=='#')
{
++(*pi);
return NULL;
}
node* root = buy_node(str[(*pi)++]);
root->l = create(str, pi);
root->r = create(str, pi);
return root;
}
void in_order(node*root)
{
if(root==NULL)return;
in_order(root->l);
printf("%c ",root->data);
in_order(root->r);
}
int main() {
char str[100];
scanf("%s",str);
int i = 0;
node*root = create(str, &i);
in_order(root);
return 0;
}