• C++10.3 查找第 k 小元素10.4 二叉排序树①


    目录

    10.3 查找第 k 小元素!

    10.4 二叉排序树①

    (1) 二叉排序树

    (2) 插入一个元素

    (3) 删除一个元素*

    (4) 查找一个元素


    10.3 查找第 k 小元素!

    和快速排序相近。不同的是,在“递归”这一阶段只需对“有第 k 小数据”的一部分进行排序,另一部分就不用管了。理想情况下,该算法的复杂度能达到线性水平。

    1. int part(int *a, int start, int end)
    2. {
    3. int low=start, high=end;
    4. int temp, check=a[start];
    5. do
    6. {
    7. while (a[high]>=check&&low<high)
    8. high--;
    9. if (a[high]<check)
    10. temp=a[high], a[high]=a[low], a[low]=temp;
    11. while (a[low]<=check&&low<high)
    12. low++;
    13. if (a[low]>check)
    14. temp=a[high], a[high]=a[low], a[low]=temp;
    15. }
    16. while (low!=high);
    17. a[low]=check;
    18. return low;
    19. }
    20. int find(int *a, int start, int end, int k)
    21. {
    22. if (start==end)
    23. return a[start];
    24. int p = part(a, start, end);
    25. int q = p-start+1; // 计算p位置的“排名”
    26. // 只对包含第k小元素的部分进行查找和排序。
    27. if (k <= q)
    28. return find(a, start, p, k);
    29. else
    30. return find(a, p+1, end, k-q);
    31. }

    如果 k 不太大,可以用堆(优先队列)解决。

    10.4 二叉排序树①

    (1) 二叉排序树

    二叉排序树的两个重要性质:
     设 R 为任意结点,则 R 的左儿子<R,R 的右儿子≥R。(如果你需要,可以把不等号的方向调换一下)
     对二叉排序树进行中序遍历,得到的一定是从小到大排好的结果。
    在本节,二叉树使用一般的定义方法,即之前的 struct node。

    (2) 插入一个元素

    插入时从顶端的根结点开始。假设插入的值为 a,对于结点 p,如果 a<p,就向左走,否则向右走,直到“无路可走”。

    1. node * insert(int v, node * p) // 调用方法:head = insert(x, head);
    2. {
    3. if (p==NULL)
    4. {
    5. NEW(p);
    6. p->value = v;
    7. }
    8. else
    9. if (v < p->value)
    10. p->leftchild=insert(v, p->leftchild);
    11. else
    12. p->rightchild=insert(v, p->rightchild);
    13. return p;
    14. }

    (3) 删除一个元素*

    删除的难点在于删除某一个结点之后,必须保持二叉排序树的性质。解决这个问题的最简单办法是用另外一个数来替换被删除的数,说得具体一点,就是用右子树中的最小值来替换被删除的值。

    1. // 删除最小值(查找最小值,只需一路向左)。
    2. // 注意:这个最小值a要么是叶子,要么只有右儿子。
    3. // 如果a有右儿子,那么只需把a的右儿子放到a的位置上。
    4. node * removemin(node * p, int &t) // 调用:head = removeitem(head, x);
    5. {
    6. if (p->leftchild == NULL)
    7. {
    8. t = p->value;
    9. return p->rightchild;
    10. }
    11. else
    12. p->leftchild = removemin(p->leftchild, t);
    13. return p;
    14. }
    15. node * removeitem(int value, node * p) // 调用:head = removeitem(x, head);
    16. {
    17. if (p==NULL) return NULL;
    18. if (value < p->value)
    19. p->leftchild = removeitem(value, p->leftchild);
    20. else if (value > p->value)
    21. p->rightchild = removeitem(value, p->rightchild);
    22. else
    23. {
    24. if (p->leftchild == NULL) // 如果只有右儿子,就直接替换
    25. return p->rightchild;
    26. else if (p->rightchild == NULL) // 如果只有左儿子,也直接替换
    27. return p->leftchild;
    28. else
    29. p->rightchild = removemin(p->rightchild, p->value);
    30. }
    31. return p;
    32. }

    (4) 查找一个元素

    和插入的过程类似。如果要找的值就是结点,停止;如果要找的值比结点小,就往左走,否则往右走。

    1. // 如果找到了,就返回一个包含结点的指针;如果找不到,就返回NULL。
    2. node * find(int value, node * p)
    3. {
    4. if (p==NULL) return NULL;
    5. if (value == p->value)
    6. return p;
    7. else if (value < p->value)
    8. return find(value, p->leftchild);
    9. else
    10. return find(value, p->rightchild);
    11. }

  • 相关阅读:
    工业制造行业如何做好主数据管理?
    Threejs中使用Tweenjs实现动画效果和Tweenjs使用说明文档
    查询快递单号物流,自动识别出物流是否签收
    vue基础语法
    【Leetcode】1216. Valid Palindrome III
    快手如何玩转复杂场景下的说话人识别?| ASRU 2021
    专利申请预审需要满足什么条件?
    想考PMP,符合报名条件么?怎么报考?
    恢复出厂设置,手机数据还能“复活”?
    【图形学】14 UnityShader语义(二)
  • 原文地址:https://blog.csdn.net/zhengheda/article/details/125621760