I am learning about heaping and I am having trouble understand how you are supposed to move each node.I will give you an example tree below:
1
/ \
2 3
/ \ / \
4 5 6 7
/ \ /
8 9 10
So that is my tree. I am trying to get 10 to the node but do not understand the steps that I take. Would I first look at the bottom of the tree? Heres my attempts:
1
/ \
2 3
/ \ / \
4 5 6 7
/ \ /
8 9 10
-> Move ten up and the two down.
1
/ \
10 3
/ \ / \
4 5 6 7
/ \ /
8 9 2
-> Move the 9 up
1
/ \
10 3
/ \ / \
9 5 6 7
/ \ /
8 4 2
-> move the 7 up
1
/ \
10 7
/ \ / \
9 5 6 3
/ \ /
8 4 2
-> Move the whole left side up and bring the 1 down.
10
/ \
9 7
/ \ / \
8 5 6 3
/ \ /
1 4 2
This is what I end up with but I have a feeling this is not right because it is not an ordered tree. Can someone help me understand where I went wrong?
Heap is not an ordered binary tree. The only ordering that heap preserves is that any child node is less (or equal) than it's parent node. Child nodes at the same level of the tree can be in any order relatively to each other.
Related
I want to use system call(s) to grab values from first data line in file file and print into legend of plot.
The command returns a syntax error. I admit come confusion about a- the use of system calls and syntax, despite reading few advanced questions here.
This is what I have:
gnuplot> plot for [i=20:30:1] '4He-processed' index i u 8:($22>0.2&&$22<2?$9:1/0):10 w yerr t system("head -2 4He-processed | tail -1 | awk '{printf "%s %8.3f %8.3f %s" , "'", $3, $4,"'"}'")
with the response: ')' expected with the pointer at the "f" in printf.
I want to have the values in $3 and $4 written to the legend.
This alternate command
gnuplot> plot for [i=20:30:1] '4He-processed' index i u 8:($22>0.2&&$22<2?$9:1/0):10 w yerr t system("head -2 4He-processed | tail -1 ")
puts the entire first line, of each index loop, to the legend
It likely has to do with syntax?
I want the values from $3 and $4, not the column headings:
Here is the some lines (but not all the columns) from the file
nz na e0 theta nu xsect ert y fy fye
2 4 0.150 60.000 0.025 0.330E+02 0.752E+00 -0.0459 0.956E+00 0.218E-01
2 4 0.150 60.000 0.030 0.497E+02 0.784E+00 -0.0001 0.146E+01 0.230E-01
2 4 0.150 60.000 0.035 0.483E+02 0.766E+00 0.0315 0.144E+01 0.229E-01
2 4 0.150 60.000 0.040 0.408E+02 0.728E+00 0.0573 0.125E+01 0.224E-01
This continues for many blocks. Here, if I were to start my loop with the first block, the values (at $3 and $4) would be 0.150 and 60.000 which correspond to the energy and angle of the projectile and they would hopefully appear in the legend. The plotted quantities ($8,$22 and $23) not pasted here (too many columns).
The problem is that the double-quoted string in your command starts with head" and runs to printf". That is clearly not what you intended.
Also I am uncertain what you mean by values in $3 and $4. Can you show an example of the first line (2 lines?) of your file and state, in words, what you are trying to extract from it?
Amended answer after seeing the data and a fuller explanation of the requirements
The answer from #theozh should work, but for completeness here is a different approach that works in either gnuplot 5.2 or 5.4.
It uses two passes through the data file; one pass to construct the titles, and a second pass for the actual plot.
$Data <<EOD
nz na e0 theta nu xsect ert y fy fye
1 11 0.150 60.000 5 6 7 8 9 10
2 12 0.150 60.000 5 6 7 8 9 10
3 13 0.150 60.000 5 6 7 8 9 10
4 14 0.150 60.000 5 6 7 8 9 10
nz na e0 theta nu xsect ert y fy fye
1 21 0.250 65.000 5 6 7 8 9 10
2 22 0.250 65.000 5 6 7 8 9 10
3 23 0.250 65.000 5 6 7 8 9 10
4 24 0.250 65.000 5 6 7 8 9 10
nz na e0 theta nu xsect ert y fy fye
1 31 0.350 70.000 5 6 7 8 9 10
2 32 0.350 70.000 5 6 7 8 9 10
3 33 0.350 70.000 5 6 7 8 9 10
4 34 0.350 70.000 5 6 7 8 9 10
EOD
set key out
set key title "e0 theta" left
#set datafile columnheader # omit this line for gnuplot version < 5.4
# columheaders are not actually used anyhow
#
# First pass is just to accummulate an array of titles
#
nblocks = 30 # maximum number of data blocks
array Title[nblocks] # one title for each data blockA
set term push # remember current terminal
set term dumb # could be anything
set out '/dev/null' # throw away the output
plot for [i=0:2:1] $Data index i using 1:2:($0 == 1 ? Title[i+1]=sprintf("%g %g",$3,$4) : "") with labels
#
# Second pass is the actual plot
#
set term pop # restore original terminal
plot for [i=0:2:1] $Data index i using 1:2 with lp title Title[i+1]
I guess you can't use columnheader() (check help columnheader), because by this you will sacrifice the first data line of each block and I assume you do want to keep all data.
The following should work for gnuplot>=5.4.0 and under the assumption that column 3 and 4 do not change within each block. However, this will not work for gnuplot<=5.4.0, because (as I understand) the title for the legend will be evaluated before each plotting iteration and in gnuplot>=5.4.0 after each plotting iteration. For gnuplot<5.4.0 you have to think about other workarounds.
I hope you get the idea and can adapt the script to your case, i.e. filtering, etc.
Script: (works for gnuplot>=5.4.0)
### extract title without using columnheader()
reset session
$Data <<EOD
nz na e0 theta nu xsect ert y fy fye
1 11 0.150 60.000 5 6 7 8 9 10
2 12 0.150 60.000 5 6 7 8 9 10
3 13 0.150 60.000 5 6 7 8 9 10
4 14 0.150 60.000 5 6 7 8 9 10
nz na e0 theta nu xsect ert y fy fye
1 21 0.250 65.000 5 6 7 8 9 10
2 22 0.250 65.000 5 6 7 8 9 10
3 23 0.250 65.000 5 6 7 8 9 10
4 24 0.250 65.000 5 6 7 8 9 10
nz na e0 theta nu xsect ert y fy fye
1 31 0.350 70.000 5 6 7 8 9 10
2 32 0.350 70.000 5 6 7 8 9 10
3 33 0.350 70.000 5 6 7 8 9 10
4 34 0.350 70.000 5 6 7 8 9 10
EOD
set key out
plot for [i=0:2:1] $Data u 1:2:(myTitle=sprintf("%g, %g",$3,$4)) index i \
w p pt 7 ps 2 lc i title myTitle
### end of script
Result:
Addition: (script for gnuplot>=4.6.0, March 2012)
What Ethan did in his answer with an array (available only from 5.2.0 on) you can do with strings and word() for older versions (check help word).
The following works for 4.6.0 and 4.6.5 and >=5.0.0, however, not for 4.6.7 (it complains that ... '+' u (NaN):(NaN) ... "Skipping data file with no valid points").
For gnuplot 4.x you cannot add spaces in your myTitles, but for gnuplot>=5.0.0 you could use double quotes and include spaces, e.g. myTitles=myTitles.sprintf(' "%g, %g"',$3,$4).
You might have to adapt the color numbers in the second plot command depending on which subblocks (index) you are plotting in the first plot command.
Data: SO74320605.dat
nz na e0 theta nu xsect ert y fy fye
1 11 0.150 60.000 5 6 7 8 9 10
2 12 0.150 60.000 5 6 7 8 9 10
3 13 0.150 60.000 5 6 7 8 9 10
4 14 0.150 60.000 5 6 7 8 9 10
nz na e0 theta nu xsect ert y fy fye
1 21 0.250 65.000 5 6 7 8 9 10
2 22 0.250 65.000 5 6 7 8 9 10
3 23 0.250 65.000 5 6 7 8 9 10
4 24 0.250 65.000 5 6 7 8 9 10
nz na e0 theta nu xsect ert y fy fye
1 31 0.350 70.000 5 6 7 8 9 10
2 32 0.350 70.000 5 6 7 8 9 10
3 33 0.350 70.000 5 6 7 8 9 10
4 34 0.350 70.000 5 6 7 8 9 10
Script: (works for gnuplot 4.6.0, 4.6.5, >=5.0.0, but not for 4.6.7)
### extract title from lines without using columnheader()
reset
FILE = "SO74320605.dat"
set key out noautotitle
myTitles = ''
plot for [i=0:2:1] FILE u 1:2:($0==1?myTitles=myTitles.sprintf(' %g,%g',$3,$4):0) \
index i w lp pt 7 ps 2 lc i+1, \
for [i=1:words(myTitles)] '+' u (NaN):(NaN) every ::::0 \
w lp pt 7 ps 2 lc i ti word(myTitles,i)
### end of script
Result: (created with gnuplot 4.6.0)
I got a sorted min-heap array: 2,3,4,5,NULL
I'd like to insert the value 1 in it, how would the first step be dealt with?
2 2
/ \ / \
3 4 or this? 3 4
/ \ / / \
5 NULL 1 5 1
Would be this the same if the node was empty instead?
A heap of integers does not have NULL values. I suppose the NULL is an indication of the capacity of the heap, meaning it can only have one more value before being full.
Would be this the same if the node was empty instead?
As unusual as this representation is, the NULL cannot mean anything else than that the node is empty. If it is considered as data, then there is an inconsistency. The data type used for the values in a heap should be consistent, and comparable. So NULL is not an option for data.
When you insert a next value, the first empty slot should be used for it. And then it should be sifted to its correct position.
So from:
2
/ \
3 4
/ \
5 NULL
to
2
/ \
3 4
/ \
5 1
to
1
/ \
2 4
/ \
5 3
BTW: a "sorted heap" is not a thing. True, a sorted list is also a heap, but the power of the heap is that it does not need to always be sorted. It only guarantees the heap property, i.e. that a parent node is never greater than either of its children.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I have the following equation :
8 ? 7 ? 6 ? 5 ? 4 ? 3 ? 2 ? 1 = 36 and I need to make a C program that finds which operators ( from +, -, *, /) go instead of ? in order to make the equation true.
My initial thought is that I have 4*7=28 different combinations. So I started making arrays adding first all + then reduce the number of + by 1 and add another symbol and see if the equation is true. But I'm confused about the direction I took.
Also I haven't found anything similar in my many google searches, so this is my last resort.
Thanks!
What a nice puzzle...
Here is my solution (which became smaller as I myself expected).
findOps.c:
#include <assert.h>
#include <stdio.h>
/* too lazy to type this everytimes out... */
typedef unsigned int uint;
/* enumeration of all supported operators */
enum {
Add, Sub, Mul, Div
};
/* It is also used as encoding for compact storage with 2 bits. */
/* extracts operator i from ops. */
uint getOp(uint ops, uint i) { return (ops >> 2 * i) & 3; }
/* solves the equation with nValue values and (nValue - 1) ops
* and returns the result.
* This considers operator precedences appropriately.
*/
int solve(uint nValues, int values[], uint ops)
{
int sum = 0; /* accu for add, subtract */
int prod = values[0]; /* accu for multiply, divide */
for (int i = 1; i < nValues; ++i) {
int arg2 = values[i];
switch (getOp(ops, i - 1)) {
case Add:
sum += prod;
prod = arg2;
break;
case Sub:
sum += prod;
prod = -arg2;
break;
case Mul:
prod *= arg2;
break;
case Div:
prod /= arg2;
break;
}
}
sum += prod;
return sum;
}
/* pretty prints the equation out of internal representation. */
void print(uint nValues, int values[], uint ops, int result)
{
char chrOp[4] = { '+', '-', '*', '/' };
printf("%d", values[0]);
for (uint i = 1; i < nValues; ++i) {
printf(" %c %d", chrOp[getOp(ops, i - 1)], values[i]);
}
printf(" == %d\n", result);
}
/* main function */
int main()
{
/* assume some kind of input which provides the arguments and intended result */
int values[] = { 8, 7, 6, 5, 4, 3, 2, 1 };
enum { nValues = sizeof values / sizeof *values };
int result = 36;
/* check all combinations of operators */
uint opsEnd = 1 << 2 * (nValues - 1);
assert(8 * sizeof opsEnd >= 2 * (nValues - 1)); /* paranoid check whether opsEnd has enough bits */
uint ops = 0;
do {
if (solve(nValues, values, ops) == result) {
print(nValues, values, ops, result);
}
} while (++ops != opsEnd);
/* done */
return 0;
}
Test in cygwin on Windows 7:
$ gcc -std=c11 -o findOps findOps.c
$ ./findOps
8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 == 36
8 * 7 - 6 * 5 + 4 + 3 + 2 + 1 == 36
8 * 7 - 6 - 5 * 4 + 3 + 2 + 1 == 36
8 + 7 * 6 - 5 * 4 + 3 + 2 + 1 == 36
8 * 7 - 6 - 5 - 4 * 3 + 2 + 1 == 36
8 + 7 * 6 - 5 - 4 * 3 + 2 + 1 == 36
8 + 7 + 6 * 5 - 4 * 3 + 2 + 1 == 36
8 * 7 / 6 * 5 - 4 * 3 + 2 + 1 == 36
8 * 7 / 6 * 5 / 4 * 3 + 2 + 1 == 36
8 / 7 * 6 * 5 + 4 + 3 - 2 + 1 == 36
8 + 7 * 6 / 5 * 4 - 3 - 2 + 1 == 36
8 + 7 - 6 + 5 * 4 + 3 * 2 + 1 == 36
8 + 7 / 6 + 5 * 4 + 3 * 2 + 1 == 36
8 * 7 / 6 + 5 * 4 + 3 * 2 + 1 == 36
8 * 7 - 6 - 5 - 4 - 3 * 2 + 1 == 36
8 + 7 * 6 - 5 - 4 - 3 * 2 + 1 == 36
8 + 7 + 6 * 5 - 4 - 3 * 2 + 1 == 36
8 * 7 / 6 * 5 - 4 - 3 * 2 + 1 == 36
8 + 7 + 6 + 5 * 4 - 3 * 2 + 1 == 36
8 / 7 * 6 + 5 + 4 * 3 * 2 + 1 == 36
8 / 7 * 6 * 5 + 4 + 3 / 2 + 1 == 36
8 + 7 + 6 * 5 * 4 / 3 / 2 + 1 == 36
8 * 7 - 6 * 5 / 4 * 3 + 2 - 1 == 36
8 * 7 + 6 - 5 * 4 - 3 - 2 - 1 == 36
8 + 7 / 6 * 5 + 4 * 3 * 2 - 1 == 36
8 - 7 + 6 * 5 + 4 * 3 / 2 - 1 == 36
8 / 7 + 6 * 5 + 4 * 3 / 2 - 1 == 36
8 - 7 + 6 + 5 * 4 * 3 / 2 - 1 == 36
8 / 7 + 6 + 5 * 4 * 3 / 2 - 1 == 36
8 - 7 / 6 + 5 * 4 * 3 / 2 - 1 == 36
8 - 7 + 6 * 5 + 4 + 3 - 2 * 1 == 36
8 / 7 + 6 * 5 + 4 + 3 - 2 * 1 == 36
8 * 7 - 6 - 5 - 4 - 3 - 2 * 1 == 36
8 + 7 * 6 - 5 - 4 - 3 - 2 * 1 == 36
8 + 7 + 6 * 5 - 4 - 3 - 2 * 1 == 36
8 * 7 / 6 * 5 - 4 - 3 - 2 * 1 == 36
8 + 7 + 6 + 5 * 4 - 3 - 2 * 1 == 36
8 + 7 + 6 + 5 + 4 * 3 - 2 * 1 == 36
8 * 7 - 6 * 5 + 4 * 3 - 2 * 1 == 36
8 + 7 + 6 + 5 + 4 + 3 * 2 * 1 == 36
8 * 7 - 6 * 5 + 4 + 3 * 2 * 1 == 36
8 * 7 - 6 - 5 * 4 + 3 * 2 * 1 == 36
8 + 7 * 6 - 5 * 4 + 3 * 2 * 1 == 36
8 * 7 + 6 - 5 * 4 - 3 * 2 * 1 == 36
8 - 7 + 6 + 5 + 4 * 3 * 2 * 1 == 36
8 / 7 + 6 + 5 + 4 * 3 * 2 * 1 == 36
8 - 7 / 6 + 5 + 4 * 3 * 2 * 1 == 36
8 - 7 + 6 * 5 + 4 + 3 / 2 * 1 == 36
8 / 7 + 6 * 5 + 4 + 3 / 2 * 1 == 36
8 / 7 * 6 * 5 + 4 * 3 / 2 * 1 == 36
8 / 7 * 6 + 5 * 4 * 3 / 2 * 1 == 36
8 * 7 - 6 * 5 * 4 / 3 / 2 * 1 == 36
8 - 7 + 6 * 5 + 4 + 3 - 2 / 1 == 36
8 / 7 + 6 * 5 + 4 + 3 - 2 / 1 == 36
8 * 7 - 6 - 5 - 4 - 3 - 2 / 1 == 36
8 + 7 * 6 - 5 - 4 - 3 - 2 / 1 == 36
8 + 7 + 6 * 5 - 4 - 3 - 2 / 1 == 36
8 * 7 / 6 * 5 - 4 - 3 - 2 / 1 == 36
8 + 7 + 6 + 5 * 4 - 3 - 2 / 1 == 36
8 + 7 + 6 + 5 + 4 * 3 - 2 / 1 == 36
8 * 7 - 6 * 5 + 4 * 3 - 2 / 1 == 36
8 + 7 + 6 + 5 + 4 + 3 * 2 / 1 == 36
8 * 7 - 6 * 5 + 4 + 3 * 2 / 1 == 36
8 * 7 - 6 - 5 * 4 + 3 * 2 / 1 == 36
8 + 7 * 6 - 5 * 4 + 3 * 2 / 1 == 36
8 * 7 + 6 - 5 * 4 - 3 * 2 / 1 == 36
8 - 7 + 6 + 5 + 4 * 3 * 2 / 1 == 36
8 / 7 + 6 + 5 + 4 * 3 * 2 / 1 == 36
8 - 7 / 6 + 5 + 4 * 3 * 2 / 1 == 36
8 - 7 + 6 * 5 + 4 + 3 / 2 / 1 == 36
8 / 7 + 6 * 5 + 4 + 3 / 2 / 1 == 36
8 / 7 * 6 * 5 + 4 * 3 / 2 / 1 == 36
8 / 7 * 6 + 5 * 4 * 3 / 2 / 1 == 36
8 * 7 - 6 * 5 * 4 / 3 / 2 / 1 == 36
$
Live Demo on coliru
In ful trust on my coding abilities, I choosed randomly one line and checked it with the Windows calculator – it was correct.
Notes:
To iterate through all possible combinations of operators, the operators +, -, *, / are mapped to 0 ... 3. As these four values can be stored with exactly 2 bits, the sequence of all operators is stored in one unsigned. This makes iteration through all possible combinations extremely easy – it's just incrementing the resp. unsigned.
To solve the equation, I remembered how ancient pocket calculators (without support of ()) did this (with very limited resources). I didn't remember clearly (as it's decades ago somebody explained it to me) but was able to re-invent it. As there are only two possible precedences in +, -, *, /, it is fully sufficient to work with two buffers – one for the accumulated intermediate product, one for the accumulated intermediate sum.
The computations are done in int arithmetic. That means these computations are mathematical correct with the constraint to Natural numbers and integer operations. (I didn't check for overflow/underflow/wrap-around but I've a "good feeling" for the sample numbers. According to how solve() works, division by 0 cannot be an issue as long as there is no 0 in input.)
What I left out: parsing the text into the data structures I used in my sample. I leave this as exercise...
If an array contains N number of elements (elements can be repeated) and the goal is to make all the elements equal by a +1 on an element and a -1 on another element in each iteration, how can we determine whether it's possible or not to normalize the array? What will be the optimal algorithm to solve the problem?
Ex.
For the array 1 2 3, if I apply +1 on 1 and -1 on 3, the array becomes 2 2 2. That means it's possible in 1 iteration.
For the array 1 2 1, it's not possible to make all the elements equal.
First, since you're not disturbing the sum by each iteration, since you're increasing one number and decreasing another, the optimal target value is going to be the average.
If this average is a whole number, you should be able to achieve it with the iterations, however if the average is a fractional number then you will not be able to achieve it.
The number of steps is going to be the sum of the distances between each number and the target, divided by 2.
Every iteration pick one number above target and one below and apply the operations to them.
PS! As per commented, if all you want is answers to the following two questions:
Can it be done
What will the value be
Then the answers are:
Yes, provided the average number is a whole number
The value repeated in the whole array is the average number
Anyway, if you want the actual operations getting from the input to the target values, here's a longer example:
1 2 3 4 5 6 7 = 28, 28/7 = 4 (optimal target)
+ -
2 2 3 4 5 6 6
+ -
3 2 3 4 5 6 5
+ -
4 2 3 4 5 6 4
+ -
4 3 3 4 5 5 4
+ -
4 4 3 4 5 4 4
+ -
4 4 4 4 4 4 4
6 steps, let's total the distances from the first number:
1 2 3 4 5 6 7
3 2 1 0 1 2 3 = 12, divided by 2 = 6
Here's the example from the comments on the question:
1 9 10 12 3 7 = 42 / 6 = 7 (optimal target)
Distances:
1 9 10 12 3 7
6 2 3 5 4 0 = 20, divided by 2 = 10 (steps)
1 9 10 12 3 7
+ - step 1
2 8 10 12 3 7
+ - step 2
3 7 10 12 3 7
+ - step 3
4 7 9 12 3 7
+ - step 4
5 7 8 12 3 7
+ - step 5
6 7 7 12 3 7
+ - step 6
7 7 7 11 3 7
- + step 7
7 7 7 10 4 7
- + step 8
7 7 7 9 5 7
- + step 9
7 7 7 8 6 7
- + step 10
7 7 7 7 7 7
Here is a more pseudo-code like algorithm description:
Calculate SUM of all the elements
COUNT all the elements
If AVERAGE (SUM/COUNT) is not whole number, solution is not possible to achieve
STEPS = SUM(ABS(numberN - AVERAGE))/2
Each iteration, pick one number below AVERAGE and one above
Apply + operation to number below and - operation to number above
Repeat steps 5 and 6 until target achieved
I have the following AVL tree:
10
/ \
5 12
/ \ / \
2 8 11 13
/ \ /\
1 4 7 9
If I insert 3 then I get:
10
/ \
5 12
/ \ / \
2 8 11 13
/ \ /\
1 4 7 9
/
3
If I calculate the Balance Factor for each node it seems that every BF is valid:
(Node:BF) -> 10:1, 5:0, 2:-1, 1:0, 4:-1, 8:0, 7:0, 9:0, 3:0, 12:0, 11:0, 13:0
But apparently this tree needs to be rebalanced. Where is there an invalid BF and then how would go about making the necessary rotations.
10 should have a balance factor of 2 with it's left subtree 5-2-4-3 and its right subtree 12-13. A valid tree after a single rotation might look like 5 | 2 10 | 1 4 8 12 | nil nil 3 nil 7 9 11 13.
A possible method for rebalancing is the cut-link-algorithm:
1. Name the unbalanced node z, one of it's child y and one of its child's child x.
2. Rename the nodes to a, b, c in inorder-traversal and let their children be T0, T1, T2 and T3 from left to right.
3. Set b as the new root, a as its left child and c as its right child.
4. Append the four subtrees corresponding from left to right as T0, T1, T2 and T3.