Преглед на файлове

quick header guard fix, started source3 which is supposed to work as a base 10 version of the trie.

tarfeef101 преди 7 години
родител
ревизия
caed7b6d06
променени са 2 файла, в които са добавени 901 реда и са изтрити 2 реда
  1. 2 2
      source2.h
  2. 899 0
      source3.h

+ 2 - 2
source2.h

@@ -1,5 +1,5 @@
-#ifndef __source1_H__
-#define __source1_H__
+#ifndef __source2_H__
+#define __source2_H__
 #include <iostream>
 #include <vector>
 using namespace std;

+ 899 - 0
source3.h

@@ -0,0 +1,899 @@
+#ifndef __source3_H__
+#define __source3_H__
+#include <iostream>
+#include <vector>
+#include <math.h>
+using namespace std;
+class Triehard // compressed decimal trie
+// constructor should make 1-10 base nodes that are empty for search to work
+// magnitude is 1 for length 1, so it must be >= 1
+// no more flag, instead we have a count field which counts the number of instances
+// the node represents. A small change, but much more functionality
+{
+	private:
+	
+		class Trienode
+		{
+			private:
+				
+				int magnitude;
+				int count;
+				Trienode * one;
+				Trienode * two;
+				Trienode * three;
+				Trienode * four;
+				Trienode * five;
+				Trienode * six;
+				Trienode * seven;
+				Trienode * eight;
+				Trienode * nine;
+				Trienode * ten;
+				
+			public:
+			
+				Trienode(int magnitude, int count):
+				magnitude{magnitude}, count{count}
+				{
+					one = nullptr;
+					two = nullptr;
+					three = nullptr;
+					four = nullptr;
+					five = nullptr;
+					six = nullptr;
+					seven = nullptr;
+					eight = nullptr;
+					nine = nullptr;
+					ten = nullptr;
+				}
+				
+				~Trienode()
+				{
+					delete one;
+					delete two;
+					delete three;
+					delete four;
+					delete five;
+					delete six;
+					delete seven;
+					delete eight;
+					delete nine;
+					delete ten;
+				}
+			
+				int getMag()
+				{
+					return magnitude;
+				}
+
+				int getCount()
+				{
+					return count;
+				}
+				
+				Trienode * getOne()
+				{
+					return one;
+				}
+				
+				Trienode * getTwo()
+				{
+					return two;
+				}
+				
+				Trienode * getThree()
+				{
+					return three;
+				}
+				
+				Trienode * getFour()
+				{
+					return four;
+				}
+				
+				Trienode * getFive()
+				{
+					return five;
+				}
+				
+				Trienode * getSix()
+				{
+					return six;
+				}
+				
+				Trienode * getSeven()
+				{
+					return seven;
+				}
+				
+				Trienode * getEight()
+				{
+					return eight;
+				}
+				
+				Trienode * getNine()
+				{
+					return nine;
+				}
+				
+				Trienode * getTen()
+				{
+					return ten;
+				}
+				
+				void addMag()
+				{
+					++magnitude;
+				}
+				
+				void subMag()
+				{
+					--magnitude;
+				}
+				
+				void addCount()
+				{
+					++count;
+				}
+				
+				void subCount()
+				{
+					--count;
+				}
+				
+				void zeroCount()
+				{
+					count = 0;
+				}
+				
+				void setCount(int x)
+				{
+					count = x;
+				}
+				
+				Trienode * setOne(int mag, int cnt)
+				{
+					one = new Trienode(mag, cnt);
+					return one;
+				}
+				
+				Trienode * setTwo(int mag, int cnt)
+				{
+					two = new Trienode(mag, cnt);
+					return two;
+				}
+				
+				Trienode * setThree(int mag, int cnt)
+				{
+					three = new Trienode(mag, cnt);
+					return three;
+				}
+				
+				Trienode * setFour(int mag, int cnt)
+				{
+					four = new Trienode(mag, cnt);
+					return four;
+				}
+				
+				Trienode * setFive(int mag, int cnt)
+				{
+					five = new Trienode(mag, cnt);
+					return five;
+				}
+				
+				Trienode * setSix(int mag, int cnt)
+				{
+					six = new Trienode(mag, cnt);
+					return six;
+				}
+				
+				Trienode * setSeven(int mag, int cnt)
+				{
+					seven = new Trienode(mag, cnt);
+					return seven;
+				}
+				
+				Trienode * setEight(int mag, int cnt)
+				{
+					eight = new Trienode(mag, cnt);
+					return eight;
+				}
+				
+				Trienode * setNine(int mag, int cnt)
+				{
+					nine = new Trienode(mag, cnt);
+					return nine;
+				}
+				
+				Trienode * setTen(int mag, int cnt)
+				{
+					ten = new Trienode(mag, cnt);
+					return ten;
+				}
+				
+				void copyOne(Trienode * node)
+				{
+					one = node;
+				}
+				
+				void copyTwo(Trienode * node)
+				{
+					two = node;
+				}
+				
+				void copyThree(Trienode * node)
+				{
+					three = node;
+				}
+				
+				void copyFour(Trienode * node)
+				{
+					four = node;
+				}
+				
+				void copyFive(Trienode * node)
+				{
+					five = node;
+				}
+				
+				void copySix(Trienode * node)
+				{
+					six = node;
+				}
+				
+				void copySeven(Trienode * node)
+				{
+					seven = node;
+				}
+				
+				void copyEight(Trienode * node)
+				{
+					eight = node;
+				}
+				
+				void copyNine(Trienode * node)
+				{
+					nine = node;
+				}
+				
+				void copyTen(Trienode * node)
+				{
+					ten = node;
+				}
+				
+				int sumMag()
+				{
+					if (left && right) return magnitude + left->sumMag() + right->sumMag();
+					if (left) return magnitude + left->sumMag();
+					if (right) return magnitude + right->sumMag();
+					return magnitude;
+				}
+    
+    			int sumCount()
+    			{
+    				if (left && right) return 1 + left->sumCount() + right->sumCount();
+    				if (left) return 1 + left->sumCount();
+    				if (right) return 1 + right->sumCount();
+    				return 1;
+    			}
+		};
+		
+		vector<Trienode *> nodes(10);
+	
+	public:
+	
+		Triehard() // Initializes both sides as empty, but makes it searchable, mutatable
+		{
+			for (int i = 0; i < 10; ++i)
+			{
+				nodes[i] = nullptr;
+			}
+		}
+		
+		~Triehard() // Same concern (syntax) as nodes, don't forget to write an erase method as well, maybe an empty/wipe
+		{
+			for (int i = 0; i < 10; ++i)
+			{
+				delete nodes[i];
+			}
+		}
+		
+		// build an array of what is "processed" so far. then when a flag is hit, print that array.
+		void mainPrint(Trienode * curnode, vector<int> * chars, int val)
+		{
+			if (!curnode) return;
+			int curmag = curnode->getMag();
+			int curcount = curnode->getCount();
+			
+			while (curmag)
+			{
+				chars->push_back(val);
+				--curmag;
+			}
+			
+			while (curcount)
+			{
+				int len = chars->size();
+				
+				for (int i = 0; i < len; i++)
+				{
+					cout << (*chars)[i] << " ";
+				}
+				cout << endl;
+				--curcount;
+			}
+			
+			for (int i = 0; i < 10; ++i)
+			{
+				mainPrint()
+			}
+			mainPrint(curnode->getLeft(), chars, 0);
+			mainPrint(curnode->getRight(), chars, 1);
+			curmag = curnode->getMag();
+			
+			while (curmag)
+			{
+				chars->pop_back();
+				--curmag;
+			}
+		}
+		
+		void myPrintIsBetterThanYoursLogan()
+		{
+			for (int i = 0; i < 10; ++i)
+			{
+				vector<int> * chars = new vector<int>();
+				mainPrint(nodes[i], chars, i);
+				delete side;
+			}
+		}
+		
+		int search(vector<int> * val) // val is the string
+		{
+			Trienode * curnode;
+			bool side; // represents if you are on the left or right (right being true)
+			if ((*val)[0])
+			{
+				curnode = right;
+				side = true;
+			}
+			else
+			{
+				curnode  = left;
+				side = false;
+			}
+			
+			int curmag = curnode->getMag();
+			
+			for (int i = 0; i < val->size(); i++) // each iteration checks the current character for accuracy. it does not prepare for the next character like the preamble
+			{
+				if ((*val)[i]) // if next digit is 1
+				{
+					if (side) // if you're on the right
+					{
+						if (curmag) // if your current magnitude is >= 1 (still info "left" in this node)
+						{
+							--curmag;
+							continue;
+						}
+						
+						if (curnode->getRight()) // If current node is "exhausted", move on to next one
+						{
+							curnode = curnode->getRight();
+							curmag = curnode->getMag() - 1;
+							continue;
+						}
+						else
+						{
+							return 0;
+						}
+						
+					}
+					else
+					{
+						if (curmag)
+						{
+							return 0;
+						}
+						
+						if (curnode->getRight())
+						{
+							curnode = curnode->getRight();
+							curmag = curnode->getMag() - 1;
+							side = true;
+							continue;
+						}
+						else
+						{
+							return 0;
+						}
+					}
+				}
+				else
+				{
+					if (!side)
+					{
+						if (curmag)
+						{
+							--curmag;
+							continue;
+						}
+						
+						if (curnode->getLeft())
+						{
+							curnode = curnode->getLeft();
+							curmag = curnode->getMag() - 1;
+							continue;
+						}
+						else
+						{
+							return 0;
+						}
+					}
+					else
+					{
+						if (curmag)
+						{
+							return 0;
+						}
+						
+						if (curnode->getLeft())
+						{
+							curnode = curnode->getLeft();
+							curmag = curnode->getMag() - 1;
+							side = false;
+							continue;
+						}
+						else
+						{
+							return 0;
+						}
+					}
+				}
+			}
+			
+			if (!curmag)
+			{
+				return curnode->getCount();
+			}
+			
+			return 0;
+		}
+		
+		void insert(vector<int> * val) // assumes valid input
+		{
+			Trienode * curnode; // the node we are checking against our current value
+			bool side; // represents if you are on the left or right (right being true)
+			if ((*val)[0])
+			{
+				curnode = right;
+				side = true;
+			}
+			else
+			{
+				curnode  = left;
+				side = false;
+			}
+			
+			int curmag = curnode->getMag(); // "remaining" magnitude of the current node
+			
+			for (int i = 0; i < val->size(); i++)
+			{
+				if ((*val)[i]) // if current digit is 1
+				{
+					if (side) // if you're on the right
+					{
+						if (curmag) // if your current magnitude is >= 1 (still info "left" in this node)
+						{
+							--curmag;
+							continue;
+						}
+						else if (curnode->getRight()) // If current node is "exhausted", move on to next one
+						{
+							curnode = curnode->getRight();
+							curmag = curnode->getMag() - 1;
+							continue;
+						}
+						else if (!(curnode->getLeft()) && !(curnode->getCount())) // if there are no subtrees, just increase this node's magnitude
+						// also can't do that if the node is flagged, since it needs to retain that info, so check for this
+						{
+							curnode->addMag();
+							continue;
+						}
+						else // we're on a "1" node, but it is depleted, and there is a left subtree. so, we create a new node to the right to represent this bit
+						// also works if the node is flagged and we just need a new node to represent the unflagged set of 1s
+						{
+							curnode = curnode->setRight(1, 0);
+							continue;
+						}
+						
+					}
+					else // we're on a left subtree, but have a 1 coming up
+					{
+						if (curmag) // this means we have a value here, so we need to split this node up, branching to the right will be handled by following code
+						{
+							Trienode * newnode = new Trienode(0, curnode->getCount()); // this will be the second half of the big node
+							curnode->zeroCount(); // this and the passing of the count into newnode ensure count is not lost
+							
+							while (curmag) // fills newnode with the extra magnitude
+							{
+								curnode->subMag();
+								--curmag;
+								newnode->addMag();
+							}
+							
+							newnode->copyLeft(curnode->getLeft()); // move the children to the bottom half
+							newnode->copyRight(curnode->getRight());
+							curnode->copyLeft(newnode); // put new node at left of curnode
+							curnode->copyRight(nullptr); // nothing is in the right yet
+							goto SKIP1; // skip next if check since we know new right is NULL
+						}
+						
+						if (curnode->getRight()) // we can and should move to the right. once there, we sub 1 from magnitude and move on.
+						{
+							curnode = curnode->getRight();
+							curmag = curnode->getMag() - 1;
+							side = true;
+							continue;
+						}
+						else // we are on left, it is empty, and the right side is empty. create and set that node to curnode->
+						{
+							SKIP1:
+							curnode = curnode->setRight(1, 0);
+							side = true;
+							continue;
+						}
+					}
+				}
+				else // next digit is a 0
+				{
+					if (!side) // on a left subtree
+					{
+						if (curmag) // still have 0s "remaining" at this node
+						{
+							--curmag;
+							continue;
+						}
+						else if (curnode->getLeft()) // no 0s remaining, but there is a left subtree
+						{
+							curnode = curnode->getLeft();
+							curmag = curnode->getMag() - 1;
+							continue;
+						}
+						else if (!(curnode->getRight()) && !(curnode->getCount())) // no subtrees and we're on the correct side, so add to this node's magnitude
+						// only if this node isn't flagged, since we must retain that info
+						{
+							curnode->addMag();
+							continue;
+						}
+						else // no 0s remaining || we are flagged, no left subtree, and we are going to add one.
+						{
+							curnode = curnode->setLeft(1, 0);
+							continue;
+						}
+					}
+					else // we're on a right subtree but have a 0 coming up
+					{
+						if (curmag) // this means we have a value here, so we need to split this node up and branch to the left before this point
+						{
+							Trienode * newnode = new Trienode(0, curnode->getCount()); // this will be the second half of the big node
+							curnode->zeroCount(); // This and the passing of getCount to newnode ensure count is not lost
+							
+							while (curmag) // fills newnode with the extra magnitude
+							{
+								curnode->subMag();
+								--curmag;
+								newnode->addMag();
+							}
+							
+							newnode->copyLeft(curnode->getLeft()); // move the children to the bottom half
+							newnode->copyRight(curnode->getRight());
+							curnode->copyLeft(nullptr); // nothing is in the left yet
+							curnode->copyRight(newnode); // put new node at right of curnode
+							goto SKIP2; // skip next if check since we know new left is NULL
+						}
+						
+						if (curnode->getLeft()) // we can and should move to the left. once there, we sub 1 from magnitude and move on.
+						{
+							curnode = curnode->getLeft();
+							curmag = curnode->getMag() - 1;
+							side = false;
+							continue;
+						}
+						else // we are on right, it is empty, and the left side is empty. create and set that node to curnode->
+						{
+							SKIP2:
+							curnode = curnode->setLeft(1, 0);
+							side = false;
+							continue;
+						}
+					}
+				}
+			}
+			
+			// at this point, the node we are at needs to be flagged. However, there is an issue: this node may have magnitude remaining
+			// if this is the case, we need to split it up at curnode->getMag() - curmag. lets check for the easy case, then proceed
+			// with that logic if necessary
+			// basically curmag is our "extra" magnitude that needs to be sent along
+			if (!curmag)
+			{
+				curnode->addCount();
+			}
+			else
+			{
+				Trienode * newnode = new Trienode(0, curnode->getCount()); // this is our new node, which should retain old flagging
+				curnode->setCount(1); // curnode will now end where we want to insert, so this should be true
+				
+				while (curmag) // fills newnode with the extra magnitude
+				{
+					curnode->subMag();
+					--curmag;
+					newnode->addMag();
+				}
+				
+				// now we create the newnode on the appropriate side
+				newnode->copyLeft(curnode->getLeft());
+				newnode->copyRight(curnode->getRight());
+				
+				if (side)
+				{
+					curnode->copyLeft(nullptr);
+					curnode->copyRight(newnode);
+				}
+				else
+				{
+					curnode->copyLeft(newnode);
+					curnode->copyRight(nullptr);
+				}
+			}
+		}
+		
+		void cut(vector<int> * val) // this is delete because i can't use delete :(
+		{
+			Trienode * curnode;
+			Trienode * prevnode = nullptr;
+			bool side; // represents if you are on the left or right (right being true)
+			bool side2; // previous node's side
+			if ((*val)[0])
+			{
+				curnode = right;
+				side = true;
+				side2 = true;
+			}
+			else
+			{
+				curnode  = left;
+				side = false;
+				side2 = false;
+			}
+			
+			int curmag = curnode->getMag();
+			
+			for (int i = 0; i < val->size(); i++) // each iteration checks the current character for accuracy. it does not prepare for the next character like the preamble
+			{
+				if ((*val)[i]) // if next digit is 1
+				{
+					if (side) // if you're on the right
+					{
+						if (curmag) // if your current magnitude is >= 1 (still info "left" in this node)
+						{
+							--curmag;
+							side2 = side;
+							continue;
+						}
+						
+						if (curnode->getRight()) // If current node is "exhausted", move on to next one
+						{
+							prevnode = curnode;
+							curnode = curnode->getRight();
+							curmag = curnode->getMag() - 1;
+							side2 = side;
+							continue;
+						}
+						else // node doesn't exist
+						{
+							return;
+						}
+						
+					}
+					else
+					{
+						if (curmag) // node doesn't exist
+						{
+							return;
+						}
+						
+						if (curnode->getRight())
+						{
+							prevnode = curnode;
+							curnode = curnode->getRight();
+							curmag = curnode->getMag() - 1;
+							side = true;
+							side2 = false;
+							continue;
+						}
+						else // node doesn't exist
+						{
+							return;
+						}
+					}
+				}
+				else
+				{
+					if (!side)
+					{
+						if (curmag)
+						{
+							--curmag;
+							side2 = side;
+							continue;
+						}
+						
+						if (curnode->getLeft())
+						{
+							prevnode = curnode;
+							curnode = curnode->getLeft();
+							curmag = curnode->getMag() - 1;
+							side2 = side;
+							continue;
+						}
+						else // node doesn't exist
+						{
+							return;
+						}
+					}
+					else
+					{
+						if (curmag) // node doesn't exist
+						{
+							return;
+						}
+						
+						if (curnode->getLeft())
+						{
+							prevnode = curnode;
+							curnode = curnode->getLeft();
+							curmag = curnode->getMag() - 1;
+							side = false;
+							side2 = true;
+							continue;
+						}
+						else // node doesn't exist
+						{
+							return;
+						}
+					}
+				}
+			}
+			
+			// at this point, we have curnode being the "end" of our value
+			if (!(prevnode)) // if we are deleting one of the 2 base trees
+			{
+				if (side)
+				{
+					right->subCount();
+				}
+				else
+				{
+					left->subCount();
+				}
+				
+				return;
+			}
+			
+			curnode->subCount(); // Normally this is all that is necessary
+			if (curnode->getCount()) return; // This means we aren't removing a node, so no compression is possible
+			
+			// Cases where nodes have to be removed/compressed
+			if (!(curnode->getLeft()) && !(curnode->getRight())) // if our node has no children, destroy it and change parent's reference to NULL
+			{
+				if (side)
+				{
+					delete curnode;
+					prevnode->copyRight(nullptr);
+				}
+				else
+				{
+					delete curnode;
+					prevnode->copyLeft(nullptr);
+				}
+			}
+			else if (side && curnode->getLeft() && prevnode->getLeft() && side2 && !(prevnode->getCount()) && !(prevnode->getLeft()))
+			// we are on the right, we have shit to the left, and the parent has nothing to the left, and is not flagged
+			// this is a rare case where we do have to compress
+			{
+				while (curnode->getMag()) // Change mag to parent
+					{
+						curnode->subMag();
+						prevnode->addMag();
+					}
+					
+					prevnode->copyLeft(curnode->getLeft()); // Move left side up, delete old data
+					curnode->copyLeft(nullptr);
+					prevnode->copyRight(nullptr);
+					delete curnode;
+			}
+			else if (!(side) && curnode->getRight() && prevnode->getRight() && !(side2) && !(prevnode->getCount()) && !(prevnode->getRight()))
+			// we are on the left, we have shit to the right, and the parent has nothing to the right, and is not flagged
+			// the same rare case as above
+			{
+				while (curnode->getMag()) // Change mag to parent
+					{
+						curnode->subMag();
+						prevnode->addMag();
+					}
+					
+					prevnode->copyRight(curnode->getRight()); // Move left side up, delete old data
+					curnode->copyRight(nullptr);
+					prevnode->copyLeft(nullptr);
+					delete curnode;
+			}
+			else if (side) // we are on the right and have shit to the right
+			{
+				Trienode * child = curnode->getRight();
+				while (child->getMag()) // moves magnitude from child to parent we are removing
+				{
+					child->subMag();
+					curnode->addMag();
+				}
+				
+				curnode->setCount(child->getCount()); // Sets count to child's count
+				
+				curnode->copyLeft(child->getLeft()); // moves child's children to our parent node
+				curnode->copyRight(child->getRight());
+				child->copyLeft(nullptr); // Change child's children to null to allow for safe deletion
+				child->copyRight(nullptr);
+				delete child;
+			}
+			else // we are on the left and have shit to the left
+			{
+				Trienode * child = curnode->getLeft();
+				while (child->getMag()) // moves magnitude from child to parent we are removing
+				{
+					child->subMag();
+					curnode->addMag();
+				}
+				
+				curnode->setCount(child->getCount()); // Sets count to child's count
+				
+				curnode->copyLeft(child->getLeft()); // moves child's children to our parent node
+				curnode->copyRight(child->getRight());
+				child->copyLeft(nullptr); // Change child's children to null to allow for safe deletion
+				child->copyRight(nullptr);
+				delete child;
+			}
+		}
+    
+    // update counter with children recursively
+	void mainCount(Trienode * curnode, int len, int right, int * counter)
+	{
+		if (!curnode) return;
+		len += curnode->getMag();
+		*counter += (len * curnode->getCount());
+		mainCount(curnode->getLeft(), len, 0, counter);
+		mainCount(curnode->getRight(), len, 1, counter);
+	}
+		
+	int countChars() // returns total word length of trie
+	{
+		int counter = 0;
+		if (left) mainCount(left, 0, 0, &counter);
+		if (right) mainCount(right, 0, 1, &counter);
+		return counter;
+	}
+    
+    float compressionovertrie() // returns nodes / nodes in a normal trie
+	{
+		float total = left->sumMag() + right->sumMag();
+		float compressed = left->sumCount() + right->sumCount();
+		return roundf(compressed/total * 100) / 100;
+	}
+    
+    float compressionoverdict() // returns nodes / sum of all word length
+    {
+    	float compressed = left->sumCount() + right->sumCount();
+    	float total = countChars();
+    	return roundf(compressed/total * 100) / 100;
+    }
+};
+
+#endif