【LB】圖形化編程與二叉樹的應用

         C語言實現圖形化編程,最直接的方式是通過graphics.h來實現,但它只在TC編譯器中能用,要想在vc中使用,目前僅有的辦法是通過easyx軟件導入函數庫。傳送門:http://www.easyx.cn/。進去後下載,將文件解壓後安裝就行。圖形編程既簡單又有意思,還能做出很多有用的東西來,推薦大家沒事去學學!
        整個程序目前實現了兩個功能,一個是通過輸入先序序列和中序序列來畫出二叉樹,另一個是通過輸入樹的廣義表(我只能這麼描述了……)來畫出二叉樹。日後準備實現自動畫出線索二叉樹。這次有源碼也有註釋。另外得益於圖形函數庫,程序可以用鼠標控制!

 

#include <stdio.h>
#include <windows.h>
#include <conio.h>
#include <stdlib.h>
#include <graphics.h>
#include <string.h>

void menu();
int check_button(int,int);
void button1(MOUSEMSG,int,int,int,int);
void button2(MOUSEMSG,int,int,int,int);

/*struct MOUSEMSG
{
	UINT uMsg;      // 當前鼠標消息
	bool mkCtrl;    // Ctrl 鍵是否按下
	bool mkShift;   // Shift 鍵是否按下
	bool mkLButton; // 鼠標左鍵是否按下
	bool mkMButton; // 鼠標中鍵是否按下
	bool mkRButton; // 鼠標右鍵是否按下
	int x;          // 當前鼠標 x 座標
	int y;          // 當前鼠標 y 座標
	int wheel;      // 鼠標滾輪滾動值
};*/

typedef struct node{
int data;
struct node *lchild;
struct node *rchild;
}btnode; //樹的結構體

int temp;  //根據樹的深度得到初始縮減值
int suojian=1;  //樹依次向下時的縮減變量
btnode *t;      //樹的根節點


btnode *create(char *pre,char *in,int n){
btnode *s;    //當前節點
char *p;      //中序數據的指針
int k;        //記錄位置
if(n<=0) return NULL;   //如果當前遞歸層次沒有數據,返回空指針
s=(btnode *)malloc(sizeof(btnode));   //爲當前節點分配內存空間
s->data=*pre;                         //當前節點賦值(先序序列的首值)
for(p=in;p<in+n;p++)
if(*p==*pre)
    break;                            //查找p的位置
k=p-in;
s->lchild=create(pre+1,in,k);         //創建當前樹的左子樹
s->rchild=create(pre+k+1,p+1,n-k-1);  //創建當前樹的右子樹
return s;                             //返回當前節點
}//根據先序和中序創建二叉樹

btnode *getree(btnode *s, char *str){
btnode *p[50],*n=NULL;
int top=-1,j=0,k;
char ch;
s=NULL;
while((ch=str[j++])!='\0'){
	switch(ch){
	case '(':top++;p[top]=n;k=1;break;
	case ')':top--;break;
	case ',':k=2;break;
	default:n=(btnode *)malloc(sizeof(btnode)); 
		     n->data=ch;n->lchild=n->rchild=NULL;
	
	if(s==NULL) 
		s=n;
	else {
		  switch(k){
	case 1:p[top]->lchild=n;break;
	case 2:p[top]->rchild=n;break;
				}
		}
}
}
return s;
}                              //創建樹


int deep(btnode *s){
	int dl,dr;
if(s==NULL) return 0;
else{
	dl=deep(s->lchild);
	dr=deep(s->rchild);
	return (dl>dr)?(dl+1):(dr+1);
}
}//求樹的深度

void draw(int x,int y,char c){
circle(x,y,20);Sleep(100);//畫圈並暫停100ms
outtextxy(x-5,y-5,c);   //輸出元素
}


void print(btnode *s,int x,int y){
if(s!=NULL) 
draw(x,y,s->data);
if(s->lchild!=NULL){
	suojian++;//縮減值自增1
line(x-14,y+14,x-temp/suojian,y+100-20);Sleep(100);//畫線並暫停100ms
print(s->lchild,x-temp/suojian,y+100);//遞歸調用左子樹
}
if(s->rchild!=NULL){
	suojian++;//縮減值自增1
line(x+14,y+14,x+temp/suojian,y+100-20);Sleep(100);//畫線並暫停100ms
print(s->rchild,x+temp/suojian,y+100);//遞歸調用右子樹
}
suojian--;
}//畫樹的遞歸算法


void main(){
IMAGE img;
initgraph(1000, 700);        //創建圖形窗口
	setfillcolor(RED);       //設置填充色
	setbkcolor(WHITE);         //設置背景色
	settextcolor(GREEN);       //設置文本顏色
	setcolor(BLACK);           //畫線的顏色
	setbkmode(TRANSPARENT);    //透明填充
	loadimage(&img,"IMAGE","back");
putimage(0,0,&img);
menu();                      
print(t,500,100);            //畫二叉樹(根節點,根節點x座標,根節點y座標)
getch();                     //暫停
}

void menu(){
	MOUSEMSG m;              //鼠標變量
	IMAGE img;
bar3d(400,200,600,250,2,true);        //畫實心條
outtextxy(420,220,"由先序和中序畫二叉樹");   //實心條中的文字
bar3d(400,260,600,310,2,true);
outtextxy(420,280,"輸入廣義表畫二叉樹");
while(1){
m=GetMouseMsg();                          //等待鼠標事件
if(m.uMsg== WM_LBUTTONDOWN)   //當鼠標左鍵點擊時break
if(check_button(m.x,m.y)==1)
{button1(m,400,200,600,250);break;}
else if(check_button(m.x,m.y)==2)
{button2(m,400,260,600,310);break;}	
}
cleardevice();	                       //清除圖形界面內容
loadimage(&img,"IMAGE","back");
putimage(0,0,&img);
setlinestyle(0,2,NULL);
}


int check_button(int x,int y){
if(x>400&&x<600&&y>200&&y<250)
return 1;
else if(x>400&&x<600&&y>260&&y<310)
return 2;
}                                     //檢查鼠標按下時的位置

void button1(MOUSEMSG m,int x1,int y1,int x2,int y2){
	int dis=1;
char xianxu[20],zhongxu[20];     //先序序列和中序序列
int n,high;                //n爲序列長度,high爲樹的高度
line(x1+dis,y1+dis,x2-dis,y1+dis);
line(x2-dis,y1+dis,x2-dis,y2-dis);
line(x2-dis,y2-dis,x1+dis,y2-dis);
line(x1+dis,y2-dis,x1+dis,y1+dis);
Sleep(200);
//xianxu="ABDGLMHEIKCFJ";
//zhongxu="MLGDHBEKIACJF";   //爲當前序列賦值
InputBox(xianxu,20,"請輸入先序序列:");
InputBox(zhongxu,20,"請輸入中序序列:");
n=strlen(xianxu);          //n獲得序列長度
t=create(xianxu,zhongxu,n);   //創建二叉樹
high=deep(t);
high--;                      //求得當前高度減1
temp=1000/high;              //獲得初始縮減值

}                                        //第一個按鍵

void button2(MOUSEMSG m,int x1,int y1,int x2,int y2){
	int dis=1;
char str[20];
line(x1+dis,y1+dis,x2-dis,y1+dis);
line(x2-dis,y1+dis,x2-dis,y2-dis);
line(x2-dis,y2-dis,x1+dis,y2-dis);
line(x1+dis,y2-dis,x1+dis,y1+dis);
Sleep(200);
//str="A(B(D(,G)),C(E,F))";  //爲當前樹賦值
    InputBox(str,20,"請輸入樹,如:A(B(D(,G)),C(E,F))");
	temp=200;
	t=getree(t,str);
}                                      //第二個按鍵

/*void outdata(){

outtextxy(20,20,"樹的線性表爲:"+xxb);
outtextxy(20,20,"其先序序列爲:"+xianxu);
outtextxy(20,20,"其先序序列爲:"+zhongxu);
outtextxy(20,20,"其後序序列爲:"+houxu);
outtextxy(20,20,"其深度爲:"+sd);
outtextxy(20,20,"其節點個數爲:"+jd);
outtextxy(20,20,"其度數爲:"+ds);
outtextxy(20,20,"度爲1的節點個數爲:"+jd1);
outtextxy(20,20,"度爲2的節點個數爲:"+jd2);
}*/                                                //這部分功能暫時未做


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章