avatar
Hey, Jochen. Uh, thanks for pointing that out. Not the smoothest experience. I'll try to take care later this week.
avatar
What doesn't seem to work well is getting authenticated to comment (using Twitter for example) without the comment being lost.
Also it seems that when using the link in the notification e-mail subsequent authentication after clicking comment doesn't bring you back to where you started. (At least not on Safari)
avatar
Heh. We'll see. Just in case you want to write/publish your own one, there is a "+" button in navbar :)
avatar
I avoid implicits like the plague.
It's yet another convenience (aka write less) taken too far.
Thanks for getting back to me.

I'd love to see similar articles about Groovy, Kotlin, Ceylon and Fantom! :)
avatar
Very true about code readability. Scala is definitely one of the tools that can produce a lot of spaghetti code unless you use the language «the right way». Just curious, how often do you use implicits?
avatar
And I would submit to you that some of the «Scala Peculiarities» should be used rarely if at all.If you don't agree on a common, simple standard for scala code in your organization, you will accumulate a lot of technical debt.Code is read more often that it is written or changed.If reading it is a chore, you've failed.And in languages like scala it is very easy to write code that is hard to read.
avatar
Oh, good catch! Resolved.P.S. There is a «code» tag for commenting code blocks, e.g.
if (Log.enabled) {
    Log.log(message)
}
avatar
You have a slight typo, should be «new DoBody» not «new DoDody»object Do{ def apply(body: => Unit) = new DoDody(body)} class DoBody(body: => Unit){ def until(cond: =>Unit): Unit = { body while(!cond) body }}
avatar
The case class example at the beginning does not generate setter methods, only getter methods. You would need to change the constructor parameters to vars to generate setter methods. By default, they're treated as vals.
avatar
Love it!
avatar
oh boy...forgot parenthesis. That's why unit tests exist.
avatar
object Mouth {
  def say(str: String) = println(str)
}

Mouth.say("Good job, Kukuruku."
avatar
The new design looks great! Go KKRK!
avatar
Thank you so much for a (very very) ^ (googol) good article, sir :D you saved my life, thank you again and again :D
avatar
What operations do you specifically mean?
avatar

Dear Hub,
Thanks for your kindly reply. I noticed that the implementation you suggested used push operation instead of recursive function. How do you think the efficiency of these two implementations?

Thanks,
Tang Laoya 
avatar
You are fun. Seriously. Unfortunately, Nikolai Ershov is not around to comment on how to improve the code. But I think your code looks good. You can also check this implementation: AVLTree.h and AVLTree.cpp.
avatar
Dear Hub,

The problem is solved after modified the function popmax as follows:
void * popmax(avltree* &p)
{
        avltree* max=findmax(p);
        void *key=max->key;
        p=remove(p,key);
        return key;
}

Do you have any suggestion to improve the code for faster speed, especially the function popmax?

Thanks,
Tang Laoya

avatar
Dear Hub,   
Sorry to bother you again. There are still some problems. 
when the code running in the latter (after many times insert/remove/popmax operations, the code will crash. 

The code is used as follows:
node *avlroot;

avlroot=insert(avlroot,(void*)t);  /// happened at many locations
...
avl=popmax(avlroot);  /// happened at many locations
...
avlroot=remove(avlroot,(void*)t); /// happened at many locations
...

/// finally
deletetree(avlroot);

Is there any problem in using the code?

Thanks,
Tang Laoya

avatar
Dear Hub, Thank you very much for your kindly reply. I posted the whole code modified based on your original code. It seems that the problem is solved (there are some problems in compare functions before). However, the code is somewhat slow when the number of elements is huge (more than one million). Could you please help me to take a look at it and give me some suggestion to improve the code? Thanks, TangLaoya
/// reference: https://kukuruku.co/hub/cpp/avl-trees
extern int avlcompare(void *item1, void *item2);
extern void externopt(void *t);
extern void externout(void *t);
#include "avl.h"

unsigned char height(node* p)
{
    return p?p->height:0;
}

int bfactor(node* p)
{
    return height(p->right)-height(p->left);
}

void fixheight(node* p)
{
    unsigned char hl = height(p->left);
    unsigned char hr = height(p->right);
    p->height = (hl>hr?hl:hr)+1;
}

node* rotateright(node* p)
{
    node* q = p->left;
    p->left = q->right;
    q->right = p;
    fixheight(p);
    fixheight(q);
    return q;
}

node* rotateleft(node* q)
{
    node* p = q->right;
    q->right = p->left;
    p->left = q;
    fixheight(q);
    fixheight(p);
    return p;
}

node* balance(node* p) // balancing the p node
{
    fixheight(p);
    if( bfactor(p)==2 )
    {
        if( bfactor(p->right) < 0 )
            p->right = rotateright(p->right);
        return rotateleft(p);
    }
    if( bfactor(p)==-2 )
    {
        if( bfactor(p->left) > 0  )
            p->left = rotateleft(p->left);
        return rotateright(p);
    }
    return p; // balancing is not required
}

node* insert(node* p, void* k) // insert k key in a tree with p root
{
    if( !p ) return new node(k);
    //if( kkey )
                if (avlcompare(k, p->key)<0)
        p->left = insert(p->left,k);
    else
        p->right = insert(p->right,k);
    return balance(p);
}

node* findmin(node* p) // find a node with minimal key in a p tree 
{
    return p->left?findmin(p->left):p;
}

node* removemin(node* p) // deleting a node with minimal key from a p tree
{
    if( p->left==0 )
        return p->right;
    p->left = removemin(p->left);
    return balance(p);
}

node* findmax(node* p) // find a node with maximal key in a p tree 
{
    return p->right?findmax(p->right):p;
}

void * popmax(node* p)
{
        node* max=findmax(p);
        void *key=max->key;
        remove(p,key);
        return key;
}

node* remove(node* p, void* k) // deleting k key from p tree
{
    if( !p ) return 0;
                int comp=avlcompare(k, p->key);
    //if( k < p->key )
    if( comp < 0 )
        p->left = remove(p->left,k);
    //else if( k > p->key )
    else if( comp > 0 )
        p->right = remove(p->right,k);  
    else //  k == p->key 
    {
        node* q = p->left;
        node* r = p->right;
        delete p;
        if( !r ) return q;
        node* min = findmin®;
        min->right = removemin®;
        min->left = q;
        return balance(min);
    }
    return balance(p);
}

void in_order_traversal(node *p)
{
        if(p)
        {
                in_order_traversal(p->left);
                externout(p->key);
                in_order_traversal(p->right);
        }
}

void pre_order_traversal(node *p)
{
        if(p)
        {
                externout(p->key);
                pre_order_traversal(p->left);
                pre_order_traversal(p->right);
        }
}

void deletetree(node *p)
{
        if(p)
        {
                deletetree(p->left);
                deletetree(p->right);
                externopt(p->key);
                delete(p);
        }
        p=0;
}