This is kind of more generic question, isn\'t language-specific. More about idea and algorithm to use.
The system is as follows:
It registers small loans bet
Intuitively, this sounds like an NP-complete problem (it reduces to a problem very like bin packing), however the following algorithm (a modified form of bin packing) should be pretty good (no time for a proof, sorry).
Net out everyone's positions, i.e. from your example above:
Alice = $4 Bill = $-4 Charles = $0
Sort all net creditors from highest to lowest, and all debtors from lowest to highest, then match by iterating over the lists.
At some point you might need to split a person's debts to net everything out - here it is probably best to split into the biggest chunks possible (i.e. into the bins with the most remaining space first).
This will take something like O(n log n) (again, proper proof needed).
See the Partition Problem and Bin Packing for more information (the former is a very similar problem, and if you limit yourself to fixed precision transactions, then it is equivalent - proof needed of course).