So I have a binary tree implementation which looks like this
struct node {
struct node *left;
struct node *right;
};
(the actual implementation is slightly more complex as there is additional data being stored as this is for a boolean algebra simplifier, but for the purpose of getting my point across I'll keep it simple)
basically I recieve a tree and I need to transform it so that it is completely left leaning
for example
a
/ \
/ \
/ \
/ \
/ \
b \
/ \ \
/ \ \
/ \ \
c \ d
/ \ \ / \
e \ f g \
/ \ \ / \ / \ \
h i j k l m n o
needs to become
g
/ \
d \
/ \ \
a \ \
/ \ \ \
f \ \ \
/ \ \ \ \
b \ \ \ \
/ \ \ \ \ \
c \ \ \ \ \
/ \ \ \ \ \ \
e \ \ \ \ \ \
/ \ \ \ \ \ \ \
h i j k l m n o
I understand the concept of tree rotations but I don't really know how to use them (or any other algorithm for that matter) to make the tree lean completely left like the diagram above
If anyone could point me in the direction of a algorithm or other resource to do this I would be very appreciative
Related
I'm playing around with building a psuedo-generic type in C. Essentially, I'm trying to clone Rust's Option<T> with a predefined, constrained list of types allowable as T.
Obviously, C isn't really suited for this -- I'm doing this primarily to see how far I can go (as opposed to something I'd expect to use in real production code). To that end, any ugly hacks are fair game.
What I have so far builds out a separate set of inner-type-specific functions for all provided types. It looks something like this:
Header:
#pragma once
#define ALL_OPTIONS \
OPTION_INSTANCE(option_bool, bool) \
OPTION_INSTANCE(option_double, double) \
OPTION_INSTANCE(option_int, int)
#define OPTION_INSTANCE(name, inner) \
typedef struct { \
bool is_some; \
inner val; \
} name##_t;
ALL_OPTIONS
#undef OPTION_INSTANCE
#define OPTION_INSTANCE(name, inner) \
name##_t name##_some(inner val); \
name##_t name##_none(void); \
bool name##_is_some(name##_t self); \
bool name##_is_none(name##_t self); \
ALL_OPTIONS
#undef OPTION_INSTANCE
Implementation:
#include "option.h"
#define OPTION_INSTANCE(name, inner) \
name##_t name##_some(inner val) { \
return (name##_t) { \
.is_some = true, \
.val = val, \
}; \
} \
\
name##_t name##_none(void) { \
return (name##_t) { \
.is_some = false, \
}; \
} \
\
bool name##_is_some(name##_t self) { \
return self.is_some; \
} \
\
bool name##_is_none(name##_t self) { \
return !self.is_some; \
}
ALL_OPTIONS
#undef OPTION_INSTANCE
Note that in my actual code I have many more functions defined for the generated types.
This works well enough, though primarily all I've done is reduce implementation boilerplate. The next step would be to implement option_is_some (no type qualification) which can accept any option_<inner>_t
I can do that well enough with a manual macro, leveraging C11 generics:
#define option_is_some(self) \
_Generic((self), \
option_bool_t: option_bool_is_some, \
option_double_t: option_double_is_some, \
option_int_t: option_int_is_some, \
)(self)
but this necessarily duplicates the list of types defined in ALL_OPTIONS. What I'd really like to do would be something like
#define OPTION_INSTANCE(name, inner) \
name##_t: name##_is_some,
#define option_is_some(self) \
_Generic((self), \
ALL_OPTIONS \
default: false \
)(self)
#undef OPTION_INSTANCE
but that fails, since ALL_OPTIONS is expanded when option_is_some is used (where OPTION_INSTANCE will be undefined).
So, I'm looking for alternatives. I'd happily move to a radically different method of defining a generic list of types (instead of the ALL_OPTIONS hack) -- however, I do want to preserve the property that adding a new supported inner type only requires a change in a single location.
Just access the member in the macro itself:
#define option_is_some(self) ((self).is_some)
Overall, your implementation is strange. Do not have a central ALL_OPTIONS place - do one option at a time, separately from each other. Files are split into headers and source files in C.
#define OPTION_HEADER(name, inner) \
typedef struct { \
bool is_some; \
inner val; \
} name##_t; \
\
name##_t name##_some(inner val); \
name##_t name##_none(void); \
bool name##_is_some(name##_t self); \
bool name##_is_none(name##_t self);
#define OPTION_SOURCE(name, inner) \
name##_t name##_some(inner val) { \
return (name##_t) { \
.is_some = true, \
.val = val, \
}; \
} \
etc...
#define OPTION_HEADER_AND_SOURCE(name, ...) \
OPTION_HEADER(name, __VA_ARGS__)
OPTION_SOURCE(name, __VA_ARGS__)
Then you would just do the options:
OPTION_HEADER_AND_SOURCE(option_bool, bool)
OPTION_HEADER_AND_SOURCE(option_double, double)
OPTION_HEADER_AND_SOURCE(option_int, int)
You can take a look at other projects that I've found: https://github.com/tylov/STC and https://github.com/glouw/ctl that use macro-ish templates to implement in C various container known from C++.
To try and describe it as concisely as possible, what I'm seeking to do is take a polynomial function such as 5*(x^2+3*x)+1 and convert it into a tree with nodes represented by
typedef struct
{
char fx [];
char * op;
node * gx;
node * hx;
} node;
where the meaning of node above is that the function fx on the node can possibly be represented as
fx = gx op hx
For example, the subfunction fx=3*x of the function mentioned above would look like fx = gx op hx where gx="3", op='*' and hx="x". But, for another example, the subfunction fx="3" could not be expressed as fx = gx op hx and so its node would look like {"3",NULL,NULL,NULL}. The tree of the subfunction fx=3*x would therefore look like
{NULL,'*', , }
/ \
/ \
/ \
/ \
/ \
/ \
`{"3",NULL,NULL,NULL}` `{"x",NULL,NULL,NULL}`
I imagined a recursive algorithm for creating the tree to work as follows, with '^' denoted the index of the array we are on as we iterate through it, and still using the function 5*(x^2+3*x)+1.
5*(x^2+3*x)+1 {NULL,NULL,NULL,NULL}
^
5*(x^2+3*x)+1 {NULL,'*', , NULL}
^ /
/
{"5",NULL,NULL,NULL}
5*(x^2+3*x)+1 {NULL,'*', , }
^ / \
/ \
/ \
/ \
/ \
/ \
/ \
/ \
/ \
{"5",NULL,NULL,NULL"} {"x^2+3*x",NULL,NULL,NULL}
5*(x^2+3*x)+1 {NULL,'+', ,NULL}
^ /
/
/
/
{NULL,'*', , }
/ \
/ \
/ \
/ \
/ \
/ \
/ \
/ \
/ \
{"5",NULL,NULL,NULL"} {"x^2+3*x",NULL,NULL,NULL}
5*(x^2+3*x)+1 {NULL,'+', ,NULL}
^ /
/
/
/
{NULL,'*', , }
/ \
/ \
/ \
/ \
/ \
/ \
/ \
/ \
/ \
{"5",NULL,NULL,NULL"} {"x^2+3*x",NULL,NULL,NULL}
5*(x^2+3*x)+1 {NULL,'+', , }
^ / \
/ \
/ {"1",NULL,NULL,NULL}
/
{NULL,'*', , }
/ \
/ \
/ \
/ \
/ \
/ \
/ \
/ \
/ \
{"5",NULL,NULL,NULL"} {"x^2+3*x",NULL,NULL,NULL}
(except the node {"x^2+3*x",NULL,NULL,NULL} would actually built into a tree by recursion ... I don't feel like writing it out above because it would take even more space).
Here's the problem, though. I just realized that my algorithm relies on the fact that the operator precedence is going a certain way. When the algorithm gets to
5*(x^2+3*x)+1
^
it knows that since the '+' sign has lower precedence than the '*' sign that separated the previous two terms "5" and "(x^2+3*x)", it should make a new root for the tree and add the subtree for the terms "5" and "(x^2+3*x)" onto the left-hand side of the tree. If, on the other hand, the function was 5+(x^2+3*x)*1 then when the algorithm gets to
`5+(x^2+3*x)*1`
^
it has to redo the tree (I'm going to start writing the tree in a more compact way now)
/ * \
5 x^2+3x
and change it to
/ + \
5 /\
/ \
/ \
/ \
x^2+3x + 1
which is a more complicated process than simply taking the tree and make it left-handside of a new root. In fact, I can't think of an algorithm for "redoing" the tree. Is there one? What does it look like? Any general hints for how I can get past this road block or how to take an entirely different approach to the problem?
For me, the simplest would be an in-order binary tree, where the operators are always a root/subroot and the constants/variables are always leaf nodes. Think I did this exact problem 30+ years ago at University...essentially reverse-polish notation, though I don't think you need to represent the ()'s except if you need to recreate the input string later.
+
/ \
/ \
* 1
/ \
/ \
5 +
/ \
/ \
^ *
/ \ / \
/ \ / \
x 2 3 x
I updated this post on 8/23 to reflect the working solution.
I'm working with the c BACnet Stack on sourceforge. http://sourceforge.net/projects/bacnet/
I'm trying to modify the demo server included in the library. The server does almost exactly what I want it to, except that I need to connect it to some other c programs that I wrote.
My problem right now is that I can't figure out how to add my own c programs into the demo server. There are several nested Makefiles in the demo. I've tried adding my file into these Makefiles, but the compiler (gcc) doesn't like it.
The latest error is:
No rule to make target ../../demo/object/test.o', needed bybacserv'. Stop.
I am not a c expert. I've been working with it my spare time for about a year. I understand the basics of a Makefile, but the Makefiles in this demo are apparently beyond me.
Is there anyone familiar with this library that might give me a little help?
Are there any better documentation than what is on the sourceforge website?
In this example I'm simply trying to add test.c to ai.c.
/demo/server/Makefile
OBJECT_SRC = \
$(BACNET_OBJECT)/device.c \
$(BACNET_OBJECT)/ai.c \
$(BACNET_OBJECT)/ao.c \
$(BACNET_OBJECT)/av.c \
$(BACNET_OBJECT)/bi.c \
$(BACNET_OBJECT)/bo.c \
$(BACNET_OBJECT)/bv.c \
$(BACNET_OBJECT)/csv.c \
$(BACNET_OBJECT)/lc.c \
$(BACNET_OBJECT)/lsp.c \
$(BACNET_OBJECT)/ms-input.c \
$(BACNET_OBJECT)/mso.c \
$(BACNET_OBJECT)/msv.c \
$(BACNET_OBJECT)/nc.c \
$(BACNET_OBJECT)/trendlog.c \
$(BACNET_OBJECT)/test.c \ <-- New entry
$(BACNET_OBJECT)/bacfile.c
/lib/Makefile
CORE_SRC = \
$(BACNET_CORE)/apdu.c \
$(BACNET_CORE)/npdu.c \
$(BACNET_CORE)/bacdcode.c \
$(BACNET_CORE)/bacint.c \
$(BACNET_CORE)/bacreal.c \
$(BACNET_CORE)/bacstr.c \
$(BACNET_CORE)/bacapp.c \
$(BACNET_CORE)/bacprop.c \
$(BACNET_CORE)/bactext.c \
$(BACNET_CORE)/datetime.c \
$(BACNET_CORE)/indtext.c \
$(BACNET_CORE)/key.c \
$(BACNET_CORE)/keylist.c \
$(BACNET_CORE)/proplist.c \
$(BACNET_CORE)/debug.c \
$(BACNET_CORE)/bigend.c \
$(BACNET_CORE)/arf.c \
$(BACNET_CORE)/awf.c \
$(BACNET_CORE)/cov.c \
$(BACNET_CORE)/dcc.c \
$(BACNET_CORE)/iam.c \
$(BACNET_CORE)/ihave.c \
$(BACNET_CORE)/rd.c \
$(BACNET_CORE)/rp.c \
$(BACNET_CORE)/rpm.c \
$(BACNET_CORE)/timesync.c \
$(BACNET_CORE)/whohas.c \
$(BACNET_CORE)/whois.c \
$(BACNET_CORE)/wp.c \
$(BACNET_CORE)/wpm.c \
$(BACNET_CORE)/abort.c \
$(BACNET_CORE)/reject.c \
$(BACNET_CORE)/bacerror.c \
$(BACNET_CORE)/ptransfer.c \
$(BACNET_CORE)/memcopy.c \
$(BACNET_CORE)/filename.c \
$(BACNET_CORE)/tsm.c \
$(BACNET_CORE)/bacaddr.c \
$(BACNET_CORE)/address.c \
$(BACNET_CORE)/bacdevobjpropref.c \
$(BACNET_CORE)/bacpropstates.c \
$(BACNET_CORE)/alarm_ack.c \
$(BACNET_CORE)/event.c \
$(BACNET_CORE)/getevent.c \
$(BACNET_CORE)/get_alarm_sum.c \
$(BACNET_CORE)/readrange.c \
$(BACNET_CORE)/timestamp.c \
$(BACNET_CORE)/test.c \ <-- Do not include test.c in this Makefile at all
$(BACNET_CORE)/version.c
new file locations:
test.c is located in /src <-- Should be located in /demo/object
test.h is located in /include <-- This works ok here
test.h
#ifndef _TEST_INCLUDE_
#define _TEST_INCLUDE_
void printit();
#endif
test.c
#include <stdio.h> <-- Needed to add #include <stdio.h>
#include "test.h"
void printit (){
printf("it....");
}
/demo/object/ai.c
...
#include "handlers.h"
#include "timestamp.h"
#include "test.h"
#include "ai.h"
...
void Analog_Input_Init(
void)
{
unsigned i;
#if defined(INTRINSIC_REPORTING)
unsigned j;
#endif
printit(); //*****************************************************************
for (i = 0; i < MAX_ANALOG_INPUTS; i++) {
printf("Initializing AI:%u\n",i);
AI_Descr[i].Present_Value = 0.0f;
AI_Descr[i].Out_Of_Service = false;
AI_Descr[i].Units = UNITS_PERCENT;
AI_Descr[i].Reliability = RELIABILITY_NO_FAULT_DETECTED;
#if defined(INTRINSIC_REPORTING)
AI_Descr[i].Event_State = EVENT_STATE_NORMAL;
/* notification class not connected */
AI_Descr[i].Notification_Class = BACNET_MAX_INSTANCE;
/* initialize Event time stamps using wildcards
and set Acked_transitions */
for (j = 0; j < MAX_BACNET_EVENT_TRANSITION; j++) {
datetime_wildcard_set(&AI_Descr[i].Event_Time_Stamps[j]);
AI_Descr[i].Acked_Transitions[j].bIsAcked = true;
}
/* Set handler for GetEventInformation function */
handler_get_event_information_set(OBJECT_ANALOG_INPUT,
Analog_Input_Event_Information);
/* Set handler for AcknowledgeAlarm function */
handler_alarm_ack_set(OBJECT_ANALOG_INPUT, Analog_Input_Alarm_Ack);
/* Set handler for GetAlarmSummary Service */
handler_get_alarm_summary_set(OBJECT_ANALOG_INPUT,
Analog_Input_Alarm_Summary);
#endif
}
}
I would say that your test.o cannot be made by gcc. The Makefile does specify to create it, though :
.c.o:
${CC} -c ${CFLAGS} $*.c -o $#
I noticed that $(BACNET_OBJECT) in /demo/server/Makefile refers to the path /demo/object
You should try to add test.c there.
And i believe you don't need to add test.c in /lib/Makefile
Long time i didnt do any C, but didnt you forget to #include <stdio.h> for printf in test.c ?
when i try to compile i got tons of those error :
km6502ot.h:77:1: error: pasting "Opcodei" and "(" does not give a valid preprocessing token
I'm on OSX, i can solve it by doing it manually for all possibilities but is it possible to fix this macro so gcc would eat it peacefully :
#define OP__(i) \
case 0x##i##: \
Opcode##i##(__THISP); \
break;
#define OP_d(i) \
case 0x##i##: \
if (__THIS__.P & D_FLAG) \
D_Opco##i##(__THISP); \
else \
Opcode##i##(__THISP); \
break;
try this
#define OP__(i) \
case 0x##i : \
Opcode##i (__THISP); \
break;
#define OP_d(i) \
case 0x##i : \
if (__THIS__.P & D_FLAG) \
D_Opco##i (__THISP); \
else \
Opcode##i (__THISP); \
break;
I have a makefile (intended for nmake) with the following contents.
w = \
abort_.obj \
backspac.obj \
c_abs.obj \
c_cos.obj \
c_div.obj \
c_exp.obj \
c_log.obj \
c_sin.obj \
c_sqrt.obj \
cabs.obj \
close.obj \
d_abs.obj \
d_acos.obj \
d_asin.obj \
d_atan.obj \
d_atn2.obj \
d_cnjg.obj \
d_cos.obj \
d_cosh.obj \
d_dim.obj \
d_exp.obj \
d_imag.obj \
d_int.obj \
d_lg10.obj \
d_log.obj \
d_mod.obj \
d_nint.obj \
d_prod.obj \
d_sign.obj \
d_sin.obj \
d_sinh.obj \
d_sqrt.obj \
d_tan.obj \
d_tanh.obj \
derf_.obj \
derfc_.obj \
dfe.obj \
dolio.obj \
dtime_.obj \
due.obj \
ef1asc_.obj \
ef1cmc_.obj \
endfile.obj \
erf_.obj \
erfc_.obj \
err.obj \
etime_.obj \
exit_.obj \
f77_aloc.obj \
f77vers.obj \
fmt.obj \
fmtlib.obj \
ftell_.obj \
getarg_.obj \
getenv_.obj \
h_abs.obj \
h_dim.obj \
h_dnnt.obj \
h_indx.obj \
h_len.obj \
h_mod.obj \
h_nint.obj \
h_sign.obj \
hl_ge.obj \
hl_gt.obj \
hl_le.obj \
hl_lt.obj \
i77vers.obj \
i_abs.obj \
i_dim.obj \
i_dnnt.obj \
i_indx.obj \
i_len.obj \
i_mod.obj \
i_nint.obj \
i_sign.obj \
iargc_.obj \
iio.obj \
ilnw.obj \
inquire.obj \
l_ge.obj \
l_gt.obj \
l_le.obj \
l_lt.obj \
lbitbits.obj \
lbitshft.obj \
lread.obj \
lwrite.obj \
main.obj \
open.obj \
pow_ci.obj \
pow_dd.obj \
pow_di.obj \
pow_hh.obj \
pow_ii.obj \
pow_ri.obj \
pow_zi.obj \
pow_zz.obj \
r_abs.obj \
r_acos.obj \
r_asin.obj \
r_atan.obj \
r_atn2.obj \
r_cnjg.obj \
r_cos.obj \
r_cosh.obj \
r_dim.obj \
r_exp.obj \
r_imag.obj \
r_int.obj \
r_lg10.obj \
r_log.obj \
r_mod.obj \
r_nint.obj \
r_sign.obj \
r_sin.obj \
r_sinh.obj \
r_sqrt.obj \
r_tan.obj \
r_tanh.obj \
rdfmt.obj \
rewind.obj \
rsfe.obj \
rsli.obj \
rsne.obj \
s_cat.obj \
s_cmp.obj \
s_copy.obj \
s_paus.obj \
s_rnge.obj \
s_stop.obj \
sfe.obj \
sig_die.obj \
signal_.obj \
sue.obj \
system_.obj \
typesize.obj \
uio.obj \
uninit.obj \
util.obj \
wref.obj \
wrtfmt.obj \
wsfe.obj \
wsle.obj \
wsne.obj \
xwsne.obj \
z_abs.obj \
z_cos.obj \
z_div.obj \
z_exp.obj \
z_log.obj \
z_sin.obj \
z_sqrt.obj
-----------snip----------------------------
vcf2c.lib: $w
lib -out:vcf2c.lib #libf2c.lbc
What does the # in front of, "libf2c.lbc," do? In a batch file # suppresses output but I don't see how that applies.
It's a LIB command file. As described on the page I linked:
You can pass command-line arguments to LIB in a command file using the
following syntax:
LIB #commandfile
The file commandfile is a text file. No space or tab is allowed
between the at sign (#) and the file name. There is no default
extension; you must specify the full file name, including any
extension. Wildcards cannot be used. You can specify an absolute or
relative path with the file name.
In the command file, arguments can be separated by spaces or tabs, as
they can on the command line; they can also be separated by newline
characters. Use a semicolon (;) to mark a comment. LIB ignores all
text from the semicolon to the end of the line.
You can specify either all or part of the command line in a command
file, and you can use more than one command file in a LIB command. LIB
accepts the command-file input as if it were specified in that
location on the command line. Command files cannot be nested. LIB
echoes the contents of command files unless the /NOLOGO option is
used.
It's a common convention on some systems (but not universally supported on any system) that a filename preceded by an # means that the program should read the contents of the file and interpret the contents as arguments to the program.
So in your case, the lib program will read in the file libf2c.lbc and use its contents as arguments.
I guess it's possible that this is a feature of nmake, I don't know much about nmake. It's certainly not part of any "traditional" make program.