Swapping Variables Without Additional Space: Previous Entries
Swapping Variables Without Additional Space: Previous Entries
Instead of writing a separate function for each data type, you could write a MACRO or templatize the function. Swapping without using a temporary variable is an age old trick and there are a few ways to do this. You could use of the basic arithmetic operations like +,-,/,*
1: void swap(int &i, int &j) 2: { 3: i=i+j; 4: j=i-j; 5: i=i-j; 6: }
The technique involves storing the sum of variables in one of them and then extracting it back by subtracting the other number. There are different variants to this technique. E.g, instead of starting by storing the sum, you could store the difference, product or the quotient. The last two could lead you to round-off and integer division errors. However all of them have one fundamental flaw. Its in line 3, and the issue is that this could lead to an overflow error. This is another technique the gets you around these issues; the XOR Swapping technique
void swap(int &i, int &j) { i = i ^ j; j = j ^ i; i = i ^ j; }
This is an elegant technique and should work well with any primitive data type and you could write a simple MACRO like
#define SWAP(i, j) (((i) ^= (j)), ((j) ^= (i)), ((i) ^= (j)))
Although, the XOR technique gets rid of the other issues like overflow and round off errors that we encountered in the previous technique, the lands in into yet another issues; This does
not work when you try to swap the same memory location. However if can get around this by a simple if check or a more elegant OR check like
#define SWAP(i, j) ( (i==j) || ((i) ^= (j)), ((j) ^= (i)), ((i) ^= (j)))
The first OR condition (i == j) is checked before the actual SWAP. (You do not need a SWAP if the both memory locations hold the same data) Posted in Algorithms, Bit Fiddling, C++, General | 7 Comments
This is how the search will look like static Node* Leaf; bool BinaryTree::Search (int data ) { Node *current = this->root; Leaf->data = data; while ( current->data != lead->data ) { if (current->data < data) { current = current->left; } else { current = current->right; } } return (current != Leaf); } The sentinel is a static node, and while building the tree, you point all the leaf nodes to this sentinel node instead of NULL. Before you start the search, you set the value of the sentinel node to the data you are searching for. This way you are guaranteed to get a hit. You just need to do one extra check at the end to see if the Hit node was a Node in the tree or the sentinel node. If you look at the number of conditional statements in the loop, there is one in the while statement and one inside the loop, that makes it 2 searches every iteration. You just saved half a conditional statement. Dont underestimate this improvement. E.g. In a 1000 iteration loop you saved 500 checks. This is extremely useful with large trees or when you are searching the tree several times or any other scenario where this call happens in a hot section. Posted in Algorithms, Binary Trees, C++, Data Structures, General, Microsoft | 13 Comments
Binary Tree Traversal: Breadth First aka Width First aka Level Order
Posted by tekpool on November 4, 2006 Binary Tree Traversal: Breadth First aka Width First aka Level Order This is the lesser know of the different kinds of binary tree traversals. Most beginner books and articles only cover the depth first searches. Breadth first traversals are an extremely important tool when working with Binary Trees. The idea is pretty nifty. Basically you work
with a Queue, and push the root node into the Queue. Then do the following until you have visited all nodes in the tree. Visit and Dequeue each element (node) in the queue, and as you visit the node, enqueue its left and right child (if present). Continue this until there are no more nodes in the queue. At this point you have finished a breadth order traversal of the binary tree. Lets work this out with an example.
Heres a small perfectly balanced tree that I going to be working with. The idea of doing a breadth first traversal is visit the nodes in the following order 1,2,3,4,5,6,7. Initially, you start of with an empty queue and enqueue the root node into the queue. I will display the contents of the queue as we move along.
------------------------------------------| 1 --------------------------------------------
Visit each element int the queue, enqueue its left and right nodes and dequeue itself. Once the elements are dequeued, I will put them to the left of the queue. Visit Node 1, enqueue 2 and 3 and dequeue 1
1 ------------------------------------------| 2, 3
--------------------------------------------
We have just finished a breadth order traversal of a binary tree Heres a pseudo-code snippet that of the solution.
BreadthOrderTraversal(BinaryTree binaryTree) { Queue queue; queue.Enqueue(binaryTree.Root); while(Queue.Size > 0) { Node n = GetFirstNodeInQueue(); queue.Enqueue(n.LeftChild); //Enqueue if exists queue.Enqueue(n.RightChild); //Enqueue if exists queue.Dequeue(); //Visit } }
Posted in Algorithms, Binary Trees, C++, Data Structures, General, Microsoft, Progamming Languages | 10 Comments
String Pattern Matching: Write a function that checks for a given pattern at the end of a given string
Posted by tekpool on October 15, 2006 String Pattern Matching: Write a function that checks for a given pattern at the end of a given string In other words, Write a function, a variant of strstr that takes in 2 strings str1 and str2 and returns true if str2 occurs at the end of the string str1, and false otherwise.
bool str_str_end(char * str1, char * str2) { // Store the base pointers of both strings char* beginStr1 = str1; char* beingStr2 = str2; // Move to the end of the strings while(*str1++); while(*str2++); for(; *str1 == *str2; str1--, Str2--) { If( str2 == beginStr2 || str1 == beingStr1) { break; } } return If(*str1 == *str2 && str2 == beginStr2 && *str1 != 0); }
Save the base addresses of the strings and then traverse to the end of the stings. To check if the string str2 occurs at the end of the string str1, start comparing characters from the end of the strings and move backwards. The function returns true when 1. All the characters in str1 match all the characters in str2 from the end. 2. The pointer str2 reaches back at the beginning of the string, which means there is nothing more to be compared 3. The strings are not empty. The above conditions are required so that the loops do not run in an infinite loop. Posted in Algorithms, C++, General, Microsoft, Pattern Matching, Progamming Languages, Strings | 2 Comments
Posted by tekpool on October 12, 2006 Q: Rectangle Intersection Find the Intersecting Rectangle In the last post, we looked into methods to determine whether or not two given rectangles intersect each other. Lets go one step ahead this time and find the intersecting rectangle. As in the previous post, I am basing the struct off of the Windows co-ordinate space, where the origin is on the top left of the screen. The x-axis moves towards the right and the y-axis moves towards the bottom.
bool Intersect(RECT* r3, const RECT * r1, const RECT * r2) { bool fIntersect = ( r2->left right && r2->right > r1->left && r2->top bottom && r2->bottom > r1->top ); if(fIntersect) { SetRect(r3, max(r1->left, r2->left), max(r1->top, r2->top), min( r1->right, r2->right), min(r1->bottom, r2->bottom)); } else { SetRect(r3, 0, 0, 0, 0); } return fIntersect; }
First, determine whether or not the two Rectangles intersect each other, Then use the SetRect method (which basically creates a RECT with the given points) and create the intersecting Rectangle
SetRect(r3, max(r1->left, r2->left), max(r1->top, r2->top), min( r1->right, r2->right), min(r1->bottom, r2->bottom));
Since the algorithm is pretty straightforward, I am not going to include more detailed analysis in this post, unless I get enough request comments or email NOTE: For all invalid rectangles passed to the function, the return value is always [0,0,0,0]. You can also choose to return error codes after checking for validity. Posted in Algorithms, C++, General, Graphics, Microsoft, Progamming Languages | 10 Comments
Rectangle Intersection Determine if two given rectangles intersect each other or not
Posted by tekpool on October 11, 2006 Q: Rectangle Intersection: Determine if two given rectangles intersect each other or not Definitions: Intersect: Two Rectangles intersect each other if the share a common area. Assumptions:
Both the rectangles are aligned with the x and y axes. Rectangles just touching each other are considered as non-intersecting.
First lets create a data structure for use in our problem. Rectangle Intersection algorithms are usually used in graphics problems. Depending on the precision needed to represent the coordinates, you may choose the required data type. In this case, I am going to use a LONG. I am also basing the struct off of the Windows co-ordinate space, where the origin is on the top left of the screen. The x-axis moves towards the right and the y-axis moves towards the bottom.
struct { LONG LONG LONG LONG } RECT;
bool IntersectRect(const RECT * r1, const RECT * r2) { return ! ( r2->left > r1->right || r2->right left || r2->top > r1->bottom || r2->bottom top ); }
The above algorithm finds the conditions at which the rectangles do not intersect and then negates the values to get the result. There is a straight forward way of doing the same algorithm, but it requires far more conditions than the one above. Consider the diagram below
| S2 | S3 | | TOP|LEFT | ----------------------------------| | | | | | S1
| S5 | S6 | | | | ----------------------------------| RIGHT|BOTTOM | | S7 | S8 | S9
S4
This is an illustration of one of the rectangles (R1). The top left corner of R2 can like in any of the 9 segments, S1 through S9. Based on each of these cases, and depending on the position of the other vertices, it can be determined whether the two rectangles R1 and R2 intersect each other. E.g. If R2s top left corner is in S1, the bottom right corner needs to be in S5 or beyond (S5,S6,S8,S9) for the rectangles to intersect. Or if the top left corner of R2 is in S5, it is an automatic case of intersection. Clearly, in this case there are a lot of cases to consider and therefore and lot of conditions to check. The conditions where the rectangles do not intersect, is where the bounds of one Rectangle is beyond the bounds of the other. The conditions are pretty straightforward as shown in the code above. Negating this value solves the original problem. There is one more conditions (negation) that can be avoided by changing the inner condition. I will leave that as an exercise for the reader. NOTE: For all invalid rectangles passed to the function, the return value is always false. You can also choose to return error codes after checking for validity. Posted in Algorithms, C++, Data Structures, General, Graphics, Microsoft, Progamming Languages | 18 Comments
predict the occurrence of un-dealt cards. The size of the data set is small (52 elements), and so the complexity of the algorithm is usually not of high concern. A O(n^2), v/s an O(n lg n) v/s an O(n) for example would be a few milliseconds. Of course, a real bad implementation with O(n^n) would certainly be of concern, although I guess it is going to be difficult to come up with a O(n^n) algorithm in the first place. It is important to look at problems with this angle. Sometimes, it takes too much time and effort to come up with a faster algorithm, and it the end it could end up providing very less value. The keyword here cost/benefit ratio. OK, so weve learnt that the complexity of the algorithm we choose is not of high priority. What else? Since this is something that will be used in a casino, we need to eliminate the element of predictability. We dont want people to be able to predict what the next card in the deck might be, even with a low probability. The problem itself involves randomization, and we are definitely going to deal with random numbers. Some random numbers, have bias on some of bits in a number, e,g rand() has a bias on the upper bits in a number. We want to be avoiding such generators. There are few basic well known solutions to this problem, the first of this is an O(n lg n) algorithm. I wont be writing code for this, but I will go over the algorithm. The solution involves simple assigning a random number to each card, and sorting them in order of their assigned number. There is a chance that two of the cards are assigned the same number. This check can be checked each time you assign a number, or even better this can be checked when you sort the cards and redo it all over again, or redo the same problem on the smaller set usually 2 cards, if you have got more than 2 cards, actually even 2 cards, then youve chosen a bad random number generator. The more elegant and faster of the two algorithms is also known as the Knuth Shuffle, popularized by Donald Knuth, in his book , The Art of Computer Programming. The algorithm was originally published by R.A. Fisher and F. Yates [Statitiscal Tables (London 1938, Example 12], in ordinary language, and by R. Durstenfeld [CACM 7 (1964), 420] in computer language. Heres the algorithm in ordinary language. Let X1, X2. XN (In this case N=52) be the set of N numbers to be shuffled. 1. 2. 3. 4. 5. 6. Set j to N Generate a random number R. (uniformly distributed between 0 and 1) Set k to (jR+1). k is now a random integer, between 1 and j. Exchange Xk and Xj Decrease j by 1. If j > 1, return to step 2.
void KnuthShuffle(int* pArr) { int rand; for(int i=51;i>=0;i--) { rand=GenRand(0,i); swap(pArr[i], pArr[rand]); } }
GenRand(int min, int max) generates a random number between min and max. For the mathematically oriented: Traditional shuffling procedures turn out to be miserable inadequate. Reportedly, expert bridge players make use of this fact when deciding whether or not to finesse. At least seven riffle shuffles of a 52-card deck are needed to reach a distribution within 10% of uniform, and 14 random riffles are guaranteed to do so. [Aldous and Diaconis, AMM 93 (1986), 333348] [Knuth, The Art of Computer Programming, Random Sampling and Shuffling] Posted in Algorithms, C++, Data Structures, General, Microsoft, Progamming Languages | 7 Comments
Prime Numbers: Finding the first N Primes Part 4 Sieve of Eratosthenes and Erdos Prime Number Theorm
Posted by tekpool on October 6, 2006 Q: Finding the first N Primes Part 4 Sieve of Eratosthenes and Erdos Prime Number Theorm We have been using regular Computer Science procedures for improving efficiency here. Its time to borrow some good old Math theorms now. The first of the techniques, that I am going to use is the Sieve of Eratosthenes This is an algorithm for making tables of primes. Sequentially write down the integers from 2 to the highest number you wish to include in the table. Cross out all numbers >2 which are divisible by 2 (every second number). Find the smallest remaining number >2 . It is 3. So cross out all numbers >3 which are divisible by 3 (every third number). Find the smallest remaining number >3 . It is 5. So cross out all numbers >5 which are divisible by 5 (every fifth number). Continue until you have crossed out all numbers divisible by sqrt(n), The numbers remaining are prime. This idea can be used easily to find all primes below a given number. But, how do you use this to find the first N primes. Heres a quick idea, Use Erdos Prime Number Theorm. You use this to find a Cap, which is the number until which you need to check to get N primes.
float FindPrimeCap(int x) { float flX = (float) x; float flCap = 1.0f; for(float f=2.0f; flCap
FindPrimeCap uses Erdos Prime Number Theorm. Since this is asymptotic, it is not accurate enough for small numbers. However, timing this code showed that this method was faster than all of the previous method we discussed.
In fact more prime were found in lesser time, using this method compared to the previous ones. In a later post, We will analye the performance of all the methods we have discussed so far Posted in Algorithms, C++, General, Microsoft, Number Theory, Progamming Languages | 1 Comment
Posted in Algorithms, C++, General, Microsoft, Number Theory, Progamming Languages | Leave a Comment
{ // Start from 5 int j=3; // Set count to 1 // 2 is already a prime int count = 1; while(count
Improvements In GetPrimesSkipEven: 1. Every second number (even) is not tested for primality 2. In primality test, division test are reduced by half, since we do not divide by even numbers any more (i+=2) 3. Modulo divisions are replaced by bit operators (i%2) == (i&1) How can we get better,
void GetPrimesSkipSecondThird(int n) { // Start from 5 int j=5; // Set count to 2, // already 2 primes have been found (2 and 3) int count = 2; while(count
Improvements In GetPrimesSkipSecondThird: 1. Every second and third number is not tested for primality 2. In primality test, division test are reduced around 60%, since we do not divide by numbers divisible be 2 or 3 Skip incrementing i by 2 or 4 (alternatively) 3. Modulo divisions are replaced by bit operators (i%2) == (i&1) In a later post, we will look into the speeds of all these, but to those curious ones out there, I am list faster algorithms as we go by