2006年09月29日

动态联编

面向对象程序设计的基本观点是用程式来仿真大千世界,这使得它的各种根本特性非常人性化,如封装、继承、多态等等,而虚拟函数就是c++中实现多态性的主将。为了实现多态性,c++编译器也革命性地提供了动态联编(或叫晚捆绑)这一特征。

  虚拟函数亦是mfc编程的关键所在,mfc编程主要有两种方法:一是响应各种消息,进行对应的消息处理。二就是重载并改写虚拟函数,来实现自己的某些要求或改变系统的某些默认处理。

  虚函数的地位是如此的重要,对它进行穷根究底,力求能知其然并知其所以然 对我们编程能力的提高大有好处。下面且听我道来。

  多态性和动态联编的实现过程分析

  一、基础略提(限于篇幅,请参阅相应的c++书籍):

  1、多态性:使用基础类的指针动态调用其派生类中函数的特性。

  2、动态联编:在运行阶段,才将函数的调用与对应的函数体进行连接的方式,又叫运行时联编或晚捆绑。

  二、过程描述:

  1、编译器发现一个类中有虚函数,编译器会立即为此类生成虚拟函数表 vtable(后面有对vtable的分析)。虚拟函数表的各表项为指向对应虚拟函数的指针。

  2、编译器在此类中隐含插入一个指针vptr(对vc编译器来说,它插在类的第一个位置上)。

  有一个办法可以让你感知这个隐含指针的存在,虽然你不能在类中直接看到它,但你可以比较一下含有虚拟函数时的类的尺寸和没有虚拟函数时的类的尺寸,你能够发现,这个指针确实存在。

  class cnovirtualfun
   {
    private:
    long lmember;
    public:
    long getmembervalue();
   } class chavevirtualfun
   {
    private:
     long lmember;
    public:
     virtual long getmembervalue();
    }

   cnovirtualfun obj;
   sizeof(obj) -> == 4;
   chavevirtualfun obj;
   sizeof(obj) -> == 8;

  3、在调用此类的构造函数时,在类的构造函数中,编译器会隐含执行vptr与vtable的关联代码,将vptr指向对应的vtable。这就将类与此类的vtable联系了起来。

  4、在调用类的构造函数时,指向基础类的指针此时已经变成指向具体的类的this指针,这样依靠此this指针即可得到正确的vtable,从而实现了多态性。在此时才能真正与函数体进行连接,这就是动态联编。
  三、vtable 分析:

  分析1:虚拟函数表包含此类及其父类的所有虚拟函数的地址。如果它没有重载父类的虚拟函数,vtable中对应表项指向其父类的此函数。反之,指向重载后的此函数。

  分析2:虚拟函数被继承后仍旧是虚拟函数,虚拟函数非常严格地按出现的顺序在 vtable 中排序,所以确定的虚拟函数对应 vtable 中一个固定的位置n,n是一个在编译时就确定的常量。所以,使用vptr加上对应的n,就可得到对应函数的入口地址。

  四、编译器调用虚拟函数的汇编码(参考think in c++):

  push funparam ;先将函数参数压栈

  push si ;将this指针压栈,以确保在当前类上操作

  mov bx,word ptr[si] ;因为vc++编译器将vptr放在类的第一个位置上,所以bx内为vptr

  call word ptr[bx+n] ;调用虚拟函数。n = 所调用的虚拟函数在对应 vtable 中的位置

  纯虚函数:

  一、引入原因:

  1、为了方便使用多态特性,我们常常需要在基类中定义虚拟函数。

  2、在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。

  为了解决上述问题,引入了纯虚函数的概念,将函数定义为纯虚函数(方法:virtual returntype function()= 0;),则编译器要求在派生类中必须予以重载以实现多态性。同时含有纯虚拟函数的类称为抽象类,它不能生成对象。这样就很好地解决了上述两个问题。

  二、纯虚函数实质:

  1、类中含有纯虚函数则它的vtable表不完全,有一个空位,所以,不能生成对象(编译器绝对不允许有调用一个不存在函数的可能)。在它的派生类中,除非重载这个函数,否则,此派生类的vtable表亦不完整,亦不能生成对象,即它也成为一个纯虚基类。

  虚函数与构造、析构函数:

  1、构造函数本身不能是虚拟函数;并且虚机制在构造函数中不起作用(在构造函数中的虚拟函数只会调用它的本地版本)。

  想一想,在基类构造函数中使用虚机制,则可能会调用到子类,此时子类尚未生成,有何后果!?。

  2、析构函数本身常常要求是虚拟函数;但虚机制在析构函数中不起作用。

  若类中使用了虚拟函数,析构函数一定要是虚拟函数,比如使用虚拟机制调用delete,没有虚拟的析构函数,怎能保证delete的是你希望delete的对象。

  虚机制也不能在析构函数中生效,因为可能会引起调用已经被delete掉的类的虚拟函数的问题。

  对象切片:

  向上映射(子类被映射到父类)的时候,会发生子类的vtable 完全变成父类的vtable的情况。这就是对象切片。

  原因:向上映射的时候,接口会变窄,而编译器绝对不允许有调用一个不存在函数的可能,所以,子类中新派生的虚拟函数的入口在vtable中会被强行“切”掉,从而出现上述情况。

  虚拟函数使用的缺点

  优点讲了一大堆,现在谈一下缺点,虚函数最主要的缺点是执行效率较低,看一看虚拟函数引发的多态性的实现过程,你就能体会到其中的原因。

2006年09月28日

拷贝构造函数还是有点难的

拷贝构造函数:具有一般构造函数的所有特性,其形参是本类的对象的引用。

作用:使用一个已经存在的对象(由拷贝构造函数的参数指定的对象)去初始化一个新的同类的对象。
根据实际问题的需要定义特定的拷贝构造函数,以实现同类对象之间数据成员的传递。若没有定义类的拷贝构造函数,系统就会自动生成一个默认函数;

功能:把初始值对象的每个数据成员的值都复制到新建立的对象中,所得到的对象和原对象具有完全相同的数据成员,即完全相同的属性。

普通构造函数是在对象创建时被调用,而拷贝构造函数在以下三种情况下都会被调用:
①当用类的一个对象去初始化该类的另一个对象时。
例如:

②如果函数的形参是类的对象,调用函数时,进行形参和实参结合时。例如:

③如果函数的返回值是类的对象,函数执行完成返回调用者时。例如:

问题:拷贝构造函数与默认的拷贝构造函数功能一样,都是直接将原对象的数据成员值—一赋给新对象中对应的数据成员。这种情况下有必要编写拷贝构造函数吗?
的确,如果情况总是这样,就没有必要特意编写一个拷贝构造函数,用默认的就行。但是,当类的数据成员中有指针类型时,默认的拷贝构造函数实现的只能是浅拷贝,浅拷贝会带来数据安全方面的隐患。要实现正确的拷贝,也就是深拷贝,必须编写拷贝构造函数。

2006年09月26日

       MFC一直在听孙鑫的讲座,对MFC有了一点的认识,绝对是入门的认识,对于MFC最难的就是记住许多函数和类,孙鑫说经常用就会记住。

       要在view 里操作要添加DC,例如CClientDC dc(this),然后对对象dc进行各种操作。

反正很多,也不知道怎么讲,慢慢来““

2006年09月21日

经常有朋友问雷神这样的问题:我在视图画的图象或者文字,当窗口改变后为什么不见了?OnDraw()和OnPaint()两个都是解决上面的问题,有什么不同?

雷神在这里一并解答一下吧。OnDraw()和OnPaint()好象兄弟俩,因为它们的工作类似。

至于不见了的问题简单,因为当你的窗口改变后,会产生无效区域,这个无效的区域需要重画。一般Windows回发送两个消息WM_PAINT(通知客户区有变化)和WM_NCPAINT(通知非客户区有变化)。非客户区的重画系统自己搞定了,而客户区的重画需要我们自己来完成。这就需要OnDraw()或OnPaint()来重画窗口。

OnDraw()和OnPaint()有什么区别呢?首先:我们先要明确CView类派生自CWnd类。而OnPaint()是CWnd的类成员,同时负责响应WM_PAINT消息。OnDraw()是CVIEW的成员函数,并且没有响应消息的功能。这就是为什么你用VC成的程序代码时,在视图类只有OnDraw没有OnPaint的原因。

其次:我们在第《每天跟我学MFC》3的开始部分已经说到了。要想在屏幕上绘图或显示图形,首先需要建立设备环境DC。其实DC是一个数据结构,它包含输出设备(不单指你17寸的纯屏显示器,还包括打印机之类的输出设备)的绘图属性的描述。MFC提供了CPaintDC类和CWindwoDC类来实时的响应,而CPaintDC支持重画。

当视图变得无效时(包括大小的改变,移动,被遮盖等等),Windows 将 WM_PAINT 消息发送给它。该视图的 OnPaint 处理函数通过创建 CPaintDC 类的DC对象来响应该消息并调用视图的 OnDraw 成员函数。通常我们不必编写重写的 OnPaint 处理成员函数。

///CView默认的标准的重画函数void CView::OnPaint(){ CPaintDC dc(this); OnPreparDC(&dc); OnDraw(&dc); //调用了OnDraw}

既然OnPaint最后也要调用OnDraw,因此我们一般会在OnDraw函数中进行绘制。下面是一个典型的程序

///视图中的绘图代码首先检索指向文档的指针,然后通过DC进行绘图调用。void CMyView::OnDraw( CDC* pDC ){ CMyDoc* pDoc = GetDocument(); CString s = pDoc->GetData(); // Returns a CString CRect rect;

GetClientRect( &rect ); pDC->SetTextAlign( TA_BASELINE | TA_CENTER ); pDC->TextOut( rect.right / 2, rect.bottom / 2, s, s.GetLength() );}

最后:现在大家明白这哥俩之间的关系了吧。因此我们一般用OnPaint维护窗口的客户区(例如我们的窗口客户区加一个背景图片),用OnDraw维护视图的客户区(例如我们通过鼠标在视图中画图)。当然你也可以不按照上面规律来,只要达到目的并且没有问题,怎么干都成。

补充:我们还可以利用Invalidate(),ValidateRgn(),ValidateRect()函数强制的重画窗口,具体的请参考MSDN吧。正文完

2006年09月19日

今天和我好友看完了这部片子,总体感觉还是怪怪的,怎么是父亲强奸女儿呢!!

片子中的恶灵其实你女儿被强奸的时候死掉一半的灵魂,她反复提醒Besty记住(Remember)被强奸的事实,而且和她妈妈说你知道真相"you know the truth"。

鬼怪的事情可能是真的,但是父亲强奸女儿的事情完全是编剧虚构的,编剧简直太变态了,这种变态的情节都能想的出来,我不建议大家看这部片子““`

如果有人看了这部片子有不懂的可以和我交流““

2006年09月14日

#include <stdio.h>

struct student

{
  int no;
  char name[20];
  int chinese;
  int maths;
  int english;
  int ave;

}stu[20];

 

int i,length=0,n;

     input_stu()

{
  float a;
  printf("Input the number of student:");
  scanf("%d",&n);
  for(i=length;i<length+n;i++)
  {
   printf("the %d student’s no: ",i+1);      scanf("%

d",&stu.no); getchar();
   printf("the %d stdent’s name: ",i+1);     scanf("%

s",stu.name);
   printf("the %d stdent’s chinese: ",i+1);  scanf("%

d",&stu.chinese);
   printf("the %d stdent’s maths: ",i+1);    scanf("%

d",&stu.maths);
   printf("the %d stdent’s english: ",i+1);  scanf("%

d",&stu.english);
   stu.ave=(stu.chinese+stu.maths+stu.english)/3;
   printf("\n");
   }
   length=length+n;
   menu2();

}

         display_stu()

{
   textcolor(9);
   printf

("\tNo\tName\tChinese\tMaths\tEnglish\tAveage\n\n");

   for(i=0;i<length;i++)
   {
    printf("  %8d%10s%8d%8d%8d%

8d\n",stu.no,stu.name,stu.chinese,stu.maths,stu.english,

stu.ave);
   }
   printf("\nInput any key to return main menu…");
   getch();
   menu2();

}

          search_stu()

{
  int k;   char ch=’y';
  textcolor(2);
  while (ch==’y')
 {
  printf("Input the student’s No:");
  scanf("%d",&k);
  for(i=0;i<length;i++)
  {
    if(stu.no==k)
    { printf("the student’s record is:\n");
      printf

("\tNo\tName\tChinese\tMaths\tEnglish\tAveage\n\n");
      printf("  %8d%10s%8d%8d%8d%

8d\n",stu.no,stu.name,stu.chinese,stu.maths,stu.english,

stu.ave);
    }
  }
  printf("\nDo you want search again(y or n)?  ");
  getchar();
  scanf("%c",&ch);
 }
  printf("\nInput any key to return main menu…");
  getch();
  menu2();

}

         modify_stu()

{
  int m,k,pos;   char ch=’y';
  textcolor(3);
  while (ch==’y')
 {
  printf("Input the student’s No to modify:");
  scanf("%d",&k);
  for(i=0;i<length;i++)
  {
    if(stu.no==k)
    { printf("the student’s record is:\n");
      printf

("\tNo\tName\tChinese\tMaths\tEnglish\tAveage\n\n");
      printf("  %8d%10s%8d%8d%8d%

8d\n",stu.no,stu.name,stu.chinese,stu.maths,stu.english,

stu.ave);
      pos=i;
     }
  }
  printf("\n\nChoose you want to modify(1-5):\n");
  printf("\t1. No  2. Name  3. Chinese  4. Maths 

5.English\n");
  scanf("%d",&m);
  switch(m)
  {
   case 1: printf("Input new No:");      scanf("%

d",&stu[pos].no);      break;
   case 2: printf("Input new Name:");    scanf("%s",stu

[pos].name);     break;
   case 3: printf("Input new chinese:"); scanf("%

d",&stu[pos].chinese); break;
   case 4: printf("Input new maths:");   scanf("%

d",&stu[pos].maths);   break;
   case 5: printf("Input new english:"); scanf("%

d",&stu[pos].english); break;
  }
  stu[pos].ave=(stu[pos].chinese+stu[pos].maths+stu

[pos].english)/3;

  printf("\nDo you want modify again(y or n)?  ");
  getchar();
  scanf("%c",&ch);
 }
  printf("\nInput any key to return main menu…");
  getch();
  menu2();

}

         sort_stu()

{
  int j,t; char ch[20];
  textcolor(13);
  printf("\n\n\t\tthe sort by aveage!\n\n");
  for(i=1;i<length;i++)
 for(j=0;j<length-i;j++)
 if(stu[j].ave<stu[j+1].ave)
 {
   t=stu[j].no;      stu[j].no=stu[j+1].no;           

stu[j+1].no=t;
   strcpy(ch,stu[j].name); strcpy(stu[j].name,stu

[j+1].name); strcpy(stu[j+1].name,ch);
   t=stu[j].chinese; stu[j].chinese=stu[j+1].chinese; 

stu[j+1].chinese=t;
   t=stu[j].maths;   stu[j].maths=stu[j+1].maths;     

stu[j+1].maths=t;
   t=stu[j].english; stu[j].english=stu[j+1].english; 

stu[j+1].english=t;
   t=stu[j].ave;     stu[j].ave=stu[j+1].ave;         

stu[j+1].ave=t;
 }
  display_stu();

}

         menu1()

{
 clrscr();  printf("\n\n\n\n");
 textcolor(9);
 printf

("\t\t**********************************************\n")

;
 printf("\t\t**                                         

**\n");
 printf("\t\t**          Welcom to Use the System!      

**\n");
 printf("\t\t**               (C语言版)                 

 **\n");
 printf("\t\t**                                         

**\n");
 printf("\t\t**           编制:

www.DesignTide.com**\n");
 printf("\t\t**                                         

**\n");
 printf("\t\t**              Copyright    2003          

**\n");
 printf("\t\t**                                         

**\n");
 printf

("\t\t**********************************************\n\n

");
 printf("\t\t Input any key to enter…");
 getch();
 menu2();

}

         menu2()

{
 int i;
 clrscr();  printf("\n\n");
 textcolor(10);
 printf

("\t\t**********************************************\n")

;
 printf("\t\t**            Main   Menu                  

**\n");
 printf("\t\t**                                         

**\n");
 printf("\t\t**       1. Input Records                  

**\n");
 printf("\t\t**       2. Display all Records            

**\n");
 printf("\t\t**       3. Search                         

**\n");
 printf("\t\t**       4. Modify                         

**\n");
 printf("\t\t**       5. Sort                           

**\n");
 printf("\t\t**       6. Exit                           

**\n");
 printf("\t\t**                                         

**\n");
 printf

("\t\t**********************************************\n\n

");
 printf("Input your choose(1-6):");
 scanf("%d",&i);

 while (i<0 || i>6)
 { printf("Your choose is error! Input again!\n");
   printf("Input your choose(1-6):");
   scanf("%d",&i);
 }

   switch(i)
   {
     case 1:    input_stu();    break;
     case 2:    display_stu();  break;
     case 3:    search_stu();   break;
     case 4:    modify_stu();   break;
     case 5:    sort_stu();     break;
     case 6:    menu3();        exit();
    }

}

         menu3()

{
 clrscr();  printf("\n\n\n\n");
 textcolor(12);
 printf

("\t\t**********************************************\n")

;
 printf("\t\t**                                         

**\n");
 printf("\t\t**                  Thanks !               

**\n");
 printf("\t\t**                                         

**\n");
 printf("\t\t**              Copyright    2003          

**\n");
 printf("\t\t**                                         

**\n");
 printf

("\t\t**********************************************\n\n

");
 getch();

}

     main()

{
 textcolor(6);
 menu1();
 getch();

}

 

 

中文修改版:

 

#define N 4

/*—-学生信息管理系统:编制 www.designtide.com—–*/

{
 clrscr();  printf("\n\n\n\n");
 textcolor(9);
 printf

("\t\t**********************************************\n")

;
 printf("\t\t**                                         

**\n");
 printf("\t\t**         欢迎使用学生信息管理系统        

**\n");
 printf("\t\t**                                         

**\n");
 printf("\t\t**               (C语言版本)               

**\n");
 printf("\t\t**                                         

**\n");
 printf("\t\t**          编制: www.DesignTide.com 

**\n");
 printf("\t\t**                                         

**\n");
 printf("\t\t**           Copyright  @   2004           

**\n");
 printf("\t\t**                                         

**\n");
 printf

("\t\t**********************************************\n\n

");
 printf("\t\t 按任意键继续……");
 getch();
 menu2();

}

 

/*—————-定义相关变量———————*/

struct student

{ char name[10];
  int num;
  int score1;
  int score2;
  float ave;
  int class;

}stu[N];

 

/*————相关数据的处理—————*/

void setup_stu_info()

{ int i;
  for(i=0;i<N;i++)
  { printf("请输入学生姓名:");
    scanf("%s",stu.name);
    printf("请输入学生学号:");
    scanf("%d",&stu.num);
    printf("请输入班级代号:");
    scanf("%d",&stu.class);
    printf("请输入第一门课程成绩:");
    scanf("%d",&stu.score1);
    printf("请输入第二门课程成绩:");
    scanf("%d",&stu.score2);
    stu.ave=(stu.score1+stu.score2)/2.0;
    printf("ave:%4.2f\n",stu.ave); }
    printf("\n\n\n");
    getch();
    ma();
 }

 

/*———–查找学生的相关信息——————*/

void search_stu_info()

{ char name[10];
  int num;
  int i,flag;
  printf("\n");
  printf("\t\t**********查找菜单***************\n");
  printf("\t\t       1.选择学号查找方式\n");
  printf("\t\t       2.选择姓名查找方式\n");

  printf("请选择查找的方式:");
  scanf("%d",&flag);
  switch(flag)
  { case 1:{printf("\t\t请输入你查找的学号:");
    scanf("%d",&num);
    printf("name\tNo\tclass\tscore1\tscore2\tave\n");
    printf

("_____________________________________________________\

n");
    printf("\n");
    for(i=0;i<N;i++)
    { if(stu.num==num)
    printf("%s\t%d\t%d\t%d\t%d\t%

4.2f\n",stu.name,stu.num,stu.class,
    stu.score1,stu.score2,stu.ave);} }
    break;

    case 2:{printf("\t\t请输入你查找的姓名:");
    scanf("%s",name);
    printf("name\tNo.\tclass\tscore1\tscore2\tave\n");
    printf

("______________________________________________________

__\n");
    printf("\n");
    for(i=0;i<N;i++)
    { if (strcmp(stu.name,name)==0)
      printf("%s\t%d\t%d\t%d\t%d\t%

4.2f\n",stu.name,stu.num,stu.class,
     stu.score1,stu.score2,stu.ave);}  }
     break;
     default:printf("\t\t输入出错!");}
   getch();
   ma();
 }

 

/*—————显示学生的相关信息——————-*/

void ouput_stu_info()

{ int i;
  printf("\n");
  printf("\t\t该学生的相关记录:\n");
  printf("\t\tNo.\tname\tclasss\tscore1\tscore2

\tave\n");
  printf("———————————————

——————–\n");
  printf("\n");
  for(i=0;i<N;i++)
  printf("%d\t%s\t%d\t%d\t%d\t%

4.2f\n",stu.num,stu.name,stu.class,
    stu.score1,stu.score2,stu.ave);
  getch();
  ma();

}

 

/*————学生总成绩排名——————*/

void stu_total_score_info()

{ int i,t,n;
  float j;
  char as[10];
  printf("\n");
  printf("\n\n\n");
  printf("No.\tname\tscore1\tscore2\tclass\tave\n");
  printf

("======================================================

==========\n");
  for(n=1;n<N;n++)
  for(i=0;i<N-n;i++)
  { if(stu.ave>stu[i+1].ave)
    {t=stu.num;stu.num=stu[i+1].num;stu[i+1].num=t;
     strcpy(as ,stu.name);strcpy(stu.name,stu

[i+1].name);strcpy(stu[i+1].name,as );
     t=stu.score1;stu.score1=stu[i+1].score1;stu

[i+1].score1=t;
     t=stu.score2;stu.score2=stu[i+1].score2;stu

[i+1].score2=t;
     t=stu.class;stu.class=stu[i+1].class;stu

[i+1].class=t;
     j=stu.ave;stu.ave=stu[i+1].ave;stu[i+1].ave=j;}
  }
  for(i=0;i<N;i++)
  printf("%d\t%s\t%d\t%d\t%d\t%

4.2f\n",stu.num,stu.name,stu.score1,
  stu.score2,stu.class,stu.ave);
  getch();
  ma();

}

 

/*—————-学生获取奖学金的情况—————–

*/

void stu_jiangxuejin_info()

{ int i;
 printf("\n\n\n");
 printf("奖学金的相关情况:\n");
 printf

("_____________________________________________________\

n");
 for(i=0;i<N;i++)
 { if(stu.ave>=90.0)
     printf("%s %d number %d class can win the teden

jinagxuejin.\n",stu.name,stu.num,stu.class);
   else if(stu.ave>=85.0)
    printf("%s %d number %d class can win the frist

jiangxuejin.\n",stu.name,stu.num,stu.class);
   else if(stu.ave>=75.0)
    printf("%s %d number %d class can win the second or

third jiangxuejin.\n",stu.name,stu.num,stu.class);
      else printf("The else person can’t win the

jiangxuejin.\n");
   printf("\n"); }
 getch();
 ma();

}

/*———————–退出学生信息管理系统———-

————-*/

go_out()

{ clrscr();
  printf("\n\n\n\n");
  printf

("\t====================================================

======\n");
  printf("\n");
  printf("\t              谢谢您使用学生信息管理系统!

\n");
  printf("\n");
  printf("\t                ***      

**************\n");
  printf("\n");
  printf

("\t====================================================

======\n");
  printf("\n");
  printf("如果你想退出,请按Alt+X.\n");
  printf("\n");
  printf("如果你想继续,请按enter键.\n");
  getch();

}

main()

{clrscr();
 printf("\n\n\n\n\n\n");
 printf

("\t====================================================

====\n");
 printf("\n");
 printf("\t                学生信息管理系统\n");
 printf("\n");
 printf

("\t====================================================

====\n");
 printf("\n\n");
 ma();

}

ma()

{ int i;
 printf("\n");
 printf

("\t****************************************************

****\n");
 printf("\n");
 printf("\t            选 择 菜 单   \n");
 printf("\n");
 printf("\t         1.输入学生信息\n");
 printf("\t         2.查找学生信息\n");
 printf("\t         3.显示学生信息\n");
 printf("\t         4.总分排名\n");
 printf("\t         5.奖学金情况\n");
 printf("\t         6.退出系统\n");
 printf("\n");
 printf("\n");
 printf

("\t****************************************************

*****\n");
 printf("\n");
 printf("选择菜单(1-6):");
 scanf("%d",&i);
 switch(i)
  { case 1:setup_stu_info();break;
    case 2:search_stu_info();break;
    case 3:ouput_stu_info();break;
    case 4:stu_total_score_info();break;
    case 5:stu_jiangxuejin_info();break;
    case 6:go_out();break;
    default: printf("输入出错!\n");
  }

}

#include <stdio.h>

struct student

{
  int no;
  char name[20];
  int chinese;
  int maths;
  int english;
  int ave;

}stu[20];

 

int i,length=0,n;

     input_stu()

{
  float a;
  printf("Input the number of student:");
  scanf("%d",&n);
  for(i=length;i<length+n;i++)
  {
   printf("the %d student’s no: ",i+1);      scanf("%

d",&stu.no); getchar();
   printf("the %d stdent’s name: ",i+1);     scanf("%

s",stu.name);
   printf("the %d stdent’s chinese: ",i+1);  scanf("%

d",&stu.chinese);
   printf("the %d stdent’s maths: ",i+1);    scanf("%

d",&stu.maths);
   printf("the %d stdent’s english: ",i+1);  scanf("%

d",&stu.english);
   stu.ave=(stu.chinese+stu.maths+stu.english)/3;
   printf("\n");
   }
   length=length+n;
   menu2();

}

         display_stu()

{
   textcolor(9);
   printf

("\tNo\tName\tChinese\tMaths\tEnglish\tAveage\n\n");

   for(i=0;i<length;i++)
   {
    printf("  %8d%10s%8d%8d%8d%

8d\n",stu.no,stu.name,stu.chinese,stu.maths,stu.english,

stu.ave);
   }
   printf("\nInput any key to return main menu…");
   getch();
   menu2();

}

          search_stu()

{
  int k;   char ch=’y';
  textcolor(2);
  while (ch==’y')
 {
  printf("Input the student’s No:");
  scanf("%d",&k);
  for(i=0;i<length;i++)
  {
    if(stu.no==k)
    { printf("the student’s record is:\n");
      printf

("\tNo\tName\tChinese\tMaths\tEnglish\tAveage\n\n");
      printf("  %8d%10s%8d%8d%8d%

8d\n",stu.no,stu.name,stu.chinese,stu.maths,stu.english,

stu.ave);
    }
  }
  printf("\nDo you want search again(y or n)?  ");
  getchar();
  scanf("%c",&ch);
 }
  printf("\nInput any key to return main menu…");
  getch();
  menu2();

}

         modify_stu()

{
  int m,k,pos;   char ch=’y';
  textcolor(3);
  while (ch==’y')
 {
  printf("Input the student’s No to modify:");
  scanf("%d",&k);
  for(i=0;i<length;i++)
  {
    if(stu.no==k)
    { printf("the student’s record is:\n");
      printf

("\tNo\tName\tChinese\tMaths\tEnglish\tAveage\n\n");
      printf("  %8d%10s%8d%8d%8d%

8d\n",stu.no,stu.name,stu.chinese,stu.maths,stu.english,

stu.ave);
      pos=i;
     }
  }
  printf("\n\nChoose you want to modify(1-5):\n");
  printf("\t1. No  2. Name  3. Chinese  4. Maths 

5.English\n");
  scanf("%d",&m);
  switch(m)
  {
   case 1: printf("Input new No:");      scanf("%

d",&stu[pos].no);      break;
   case 2: printf("Input new Name:");    scanf("%s",stu

[pos].name);     break;
   case 3: printf("Input new chinese:"); scanf("%

d",&stu[pos].chinese); break;
   case 4: printf("Input new maths:");   scanf("%

d",&stu[pos].maths);   break;
   case 5: printf("Input new english:"); scanf("%

d",&stu[pos].english); break;
  }
  stu[pos].ave=(stu[pos].chinese+stu[pos].maths+stu

[pos].english)/3;

  printf("\nDo you want modify again(y or n)?  ");
  getchar();
  scanf("%c",&ch);
 }
  printf("\nInput any key to return main menu…");
  getch();
  menu2();

}

         sort_stu()

{
  int j,t; char ch[20];
  textcolor(13);
  printf("\n\n\t\tthe sort by aveage!\n\n");
  for(i=1;i<length;i++)
 for(j=0;j<length-i;j++)
 if(stu[j].ave<stu[j+1].ave)
 {
   t=stu[j].no;      stu[j].no=stu[j+1].no;           

stu[j+1].no=t;
   strcpy(ch,stu[j].name); strcpy(stu[j].name,stu

[j+1].name); strcpy(stu[j+1].name,ch);
   t=stu[j].chinese; stu[j].chinese=stu[j+1].chinese; 

stu[j+1].chinese=t;
   t=stu[j].maths;   stu[j].maths=stu[j+1].maths;     

stu[j+1].maths=t;
   t=stu[j].english; stu[j].english=stu[j+1].english; 

stu[j+1].english=t;
   t=stu[j].ave;     stu[j].ave=stu[j+1].ave;         

stu[j+1].ave=t;
 }
  display_stu();

}

         menu1()

{
 clrscr();  printf("\n\n\n\n");
 textcolor(9);
 printf

("\t\t**********************************************\n")

;
 printf("\t\t**                                         

**\n");
 printf("\t\t**          Welcom to Use the System!      

**\n");
 printf("\t\t**               (C语言版)                 

 **\n");
 printf("\t\t**                                         

**\n");
 printf("\t\t**           编制:

www.DesignTide.com**\n");
 printf("\t\t**                                         

**\n");
 printf("\t\t**              Copyright    2003          

**\n");
 printf("\t\t**                                         

**\n");
 printf

("\t\t**********************************************\n\n

");
 printf("\t\t Input any key to enter…");
 getch();
 menu2();

}

         menu2()

{
 int i;
 clrscr();  printf("\n\n");
 textcolor(10);
 printf

("\t\t**********************************************\n")

;
 printf("\t\t**            Main   Menu                  

**\n");
 printf("\t\t**                                         

**\n");
 printf("\t\t**       1. Input Records                  

**\n");
 printf("\t\t**       2. Display all Records            

**\n");
 printf("\t\t**       3. Search                         

**\n");
 printf("\t\t**       4. Modify                         

**\n");
 printf("\t\t**       5. Sort                           

**\n");
 printf("\t\t**       6. Exit                           

**\n");
 printf("\t\t**                                         

**\n");
 printf

("\t\t**********************************************\n\n

");
 printf("Input your choose(1-6):");
 scanf("%d",&i);

 while (i<0 || i>6)
 { printf("Your choose is error! Input again!\n");
   printf("Input your choose(1-6):");
   scanf("%d",&i);
 }

   switch(i)
   {
     case 1:    input_stu();    break;
     case 2:    display_stu();  break;
     case 3:    search_stu();   break;
     case 4:    modify_stu();   break;
     case 5:    sort_stu();     break;
     case 6:    menu3();        exit();
    }

}

         menu3()

{
 clrscr();  printf("\n\n\n\n");
 textcolor(12);
 printf

("\t\t**********************************************\n")

;
 printf("\t\t**                                         

**\n");
 printf("\t\t**                  Thanks !               

**\n");
 printf("\t\t**                                         

**\n");
 printf("\t\t**              Copyright    2003          

**\n");
 printf("\t\t**                                         

**\n");
 printf

("\t\t**********************************************\n\n

");
 getch();

}

     main()

{
 textcolor(6);
 menu1();
 getch();

}

 

 

中文修改版:

 

#define N 4

/*—-学生信息管理系统:编制 www.designtide.com—–*/

{
 clrscr();  printf("\n\n\n\n");
 textcolor(9);
 printf

("\t\t**********************************************\n")

;
 printf("\t\t**                                         

**\n");
 printf("\t\t**         欢迎使用学生信息管理系统        

**\n");
 printf("\t\t**                                         

**\n");
 printf("\t\t**               (C语言版本)               

**\n");
 printf("\t\t**                                         

**\n");
 printf("\t\t**          编制: www.DesignTide.com 

**\n");
 printf("\t\t**                                         

**\n");
 printf("\t\t**           Copyright  @   2004           

**\n");
 printf("\t\t**                                         

**\n");
 printf

("\t\t**********************************************\n\n

");
 printf("\t\t 按任意键继续……");
 getch();
 menu2();

}

 

/*—————-定义相关变量———————*/

struct student

{ char name[10];
  int num;
  int score1;
  int score2;
  float ave;
  int class;

}stu[N];

 

/*————相关数据的处理—————*/

void setup_stu_info()

{ int i;
  for(i=0;i<N;i++)
  { printf("请输入学生姓名:");
    scanf("%s",stu.name);
    printf("请输入学生学号:");
    scanf("%d",&stu.num);
    printf("请输入班级代号:");
    scanf("%d",&stu.class);
    printf("请输入第一门课程成绩:");
    scanf("%d",&stu.score1);
    printf("请输入第二门课程成绩:");
    scanf("%d",&stu.score2);
    stu.ave=(stu.score1+stu.score2)/2.0;
    printf("ave:%4.2f\n",stu.ave); }
    printf("\n\n\n");
    getch();
    ma();
 }

 

/*———–查找学生的相关信息——————*/

void search_stu_info()

{ char name[10];
  int num;
  int i,flag;
  printf("\n");
  printf("\t\t**********查找菜单***************\n");
  printf("\t\t       1.选择学号查找方式\n");
  printf("\t\t       2.选择姓名查找方式\n");

  printf("请选择查找的方式:");
  scanf("%d",&flag);
  switch(flag)
  { case 1:{printf("\t\t请输入你查找的学号:");
    scanf("%d",&num);
    printf("name\tNo\tclass\tscore1\tscore2\tave\n");
    printf

("_____________________________________________________\

n");
    printf("\n");
    for(i=0;i<N;i++)
    { if(stu.num==num)
    printf("%s\t%d\t%d\t%d\t%d\t%

4.2f\n",stu.name,stu.num,stu.class,
    stu.score1,stu.score2,stu.ave);} }
    break;

    case 2:{printf("\t\t请输入你查找的姓名:");
    scanf("%s",name);
    printf("name\tNo.\tclass\tscore1\tscore2\tave\n");
    printf

("______________________________________________________

__\n");
    printf("\n");
    for(i=0;i<N;i++)
    { if (strcmp(stu.name,name)==0)
      printf("%s\t%d\t%d\t%d\t%d\t%

4.2f\n",stu.name,stu.num,stu.class,
     stu.score1,stu.score2,stu.ave);}  }
     break;
     default:printf("\t\t输入出错!");}
   getch();
   ma();
 }

 

/*—————显示学生的相关信息——————-*/

void ouput_stu_info()

{ int i;
  printf("\n");
  printf("\t\t该学生的相关记录:\n");
  printf("\t\tNo.\tname\tclasss\tscore1\tscore2

\tave\n");
  printf("———————————————

——————–\n");
  printf("\n");
  for(i=0;i<N;i++)
  printf("%d\t%s\t%d\t%d\t%d\t%

4.2f\n",stu.num,stu.name,stu.class,
    stu.score1,stu.score2,stu.ave);
  getch();
  ma();

}

 

/*————学生总成绩排名——————*/

void stu_total_score_info()

{ int i,t,n;
  float j;
  char as[10];
  printf("\n");
  printf("\n\n\n");
  printf("No.\tname\tscore1\tscore2\tclass\tave\n");
  printf

("======================================================

==========\n");
  for(n=1;n<N;n++)
  for(i=0;i<N-n;i++)
  { if(stu.ave>stu[i+1].ave)
    {t=stu.num;stu.num=stu[i+1].num;stu[i+1].num=t;
     strcpy(as ,stu.name);strcpy(stu.name,stu

[i+1].name);strcpy(stu[i+1].name,as );
     t=stu.score1;stu.score1=stu[i+1].score1;stu

[i+1].score1=t;
     t=stu.score2;stu.score2=stu[i+1].score2;stu

[i+1].score2=t;
     t=stu.class;stu.class=stu[i+1].class;stu

[i+1].class=t;
     j=stu.ave;stu.ave=stu[i+1].ave;stu[i+1].ave=j;}
  }
  for(i=0;i<N;i++)
  printf("%d\t%s\t%d\t%d\t%d\t%

4.2f\n",stu.num,stu.name,stu.score1,
  stu.score2,stu.class,stu.ave);
  getch();
  ma();

}

 

/*—————-学生获取奖学金的情况—————–

*/

void stu_jiangxuejin_info()

{ int i;
 printf("\n\n\n");
 printf("奖学金的相关情况:\n");
 printf

("_____________________________________________________\

n");
 for(i=0;i<N;i++)
 { if(stu.ave>=90.0)
     printf("%s %d number %d class can win the teden

jinagxuejin.\n",stu.name,stu.num,stu.class);
   else if(stu.ave>=85.0)
    printf("%s %d number %d class can win the frist

jiangxuejin.\n",stu.name,stu.num,stu.class);
   else if(stu.ave>=75.0)
    printf("%s %d number %d class can win the second or

third jiangxuejin.\n",stu.name,stu.num,stu.class);
      else printf("The else person can’t win the

jiangxuejin.\n");
   printf("\n"); }
 getch();
 ma();

}

/*———————–退出学生信息管理系统———-

————-*/

go_out()

{ clrscr();
  printf("\n\n\n\n");
  printf

("\t====================================================

======\n");
  printf("\n");
  printf("\t              谢谢您使用学生信息管理系统!

\n");
  printf("\n");
  printf("\t                ***      

**************\n");
  printf("\n");
  printf

("\t====================================================

======\n");
  printf("\n");
  printf("如果你想退出,请按Alt+X.\n");
  printf("\n");
  printf("如果你想继续,请按enter键.\n");
  getch();

}

main()

{clrscr();
 printf("\n\n\n\n\n\n");
 printf

("\t====================================================

====\n");
 printf("\n");
 printf("\t                学生信息管理系统\n");
 printf("\n");
 printf

("\t====================================================

====\n");
 printf("\n\n");
 ma();

}

ma()

{ int i;
 printf("\n");
 printf

("\t****************************************************

****\n");
 printf("\n");
 printf("\t            选 择 菜 单   \n");
 printf("\n");
 printf("\t         1.输入学生信息\n");
 printf("\t         2.查找学生信息\n");
 printf("\t         3.显示学生信息\n");
 printf("\t         4.总分排名\n");
 printf("\t         5.奖学金情况\n");
 printf("\t         6.退出系统\n");
 printf("\n");
 printf("\n");
 printf

("\t****************************************************

*****\n");
 printf("\n");
 printf("选择菜单(1-6):");
 scanf("%d",&i);
 switch(i)
  { case 1:setup_stu_info();break;
    case 2:search_stu_info();break;
    case 3:ouput_stu_info();break;
    case 4:stu_total_score_info();break;
    case 5:stu_jiangxuejin_info();break;
    case 6:go_out();break;
    default: printf("输入出错!\n");
  }

}

2006年09月12日

空间数据挖掘技术理论及方法
葛继科
(西南农业大学信息学院 400716)
 
摘要  本文简要论述了空间数据库技术及空间数据挖掘技术的理论及特点,分析了空间数据挖掘技术的层次、方法,并重点介绍了当前常用的分类、聚类、关联规则等空间数据挖掘方法,指出了当前空间数据挖掘技术中尚需解决的问题、发展趋势及方向。
关键词 空间数据挖掘 分类 聚类 关联规则 
0 引言
地理信息系统(Geographic Information System,简称GIS)是计算机科学、地理学、测量学、地图学等多门学科综合的技术[1]。GIS的基本技术是空间数据库、地图可视化及空间分析,而空间数据库是GIS的关键。空间数据挖掘技术作为当前数据库技术最活跃的分支与知识获取手段,在GIS中的应用推动着GIS朝智能化和集成化的方向发展。
1 空间数据库与空间数据挖掘技术的特点
随着数据库技术的不断发展和数据库管理系统的广泛应用,数据库中存储的数据量也在急剧增大,在这些海量数据的背后隐藏了很多具有决策意义的信息。但是,现今数据库的大多数应用仍然停留在查询、检索阶段,数据库中隐藏的丰富的知识远远没有得到充分的发掘和利用,数据库中数据的急剧增长和人们对数据库处理和理解的困难形成了强烈的反差,导致“人们被数据淹没,但却饥饿于知识”的现象。
空间数据库(数据仓库)中的空间数据除了其显式信息外,还具有丰富的隐含信息,如数字高程模型〔DEM或TIN〕,除了载荷高程信息外,还隐含了地质岩性与构造方面的信息;植物的种类是显式信息,但其中还隐含了气候的水平地带性和垂直地带性的信息,等等。这些隐含的信息只有通过数据挖掘才能显示出来。空间数据挖掘(Spatial Data Mining,简称SDM),或者称为从空间数据库中发现知识,是为了解决空间数据海量特性而扩展的一个新的数据挖掘的研究分支,是指从空间数据库中提取隐含的、用户感兴趣的空间或非空间的模式和普遍特征的过程[2]。由于SDM的对象主要是空间数据库,而空间数据库中不仅存储了空间事物或对象的几何数据、属性数据,而且存储了空间事物或对象之间的图形空间关系,因此其处理方法有别于一般的数据挖掘方法。SDM与传统的地学数据分析方法的本质区别在于SDM是在没有明确假设的前提下去挖掘信息、发现知识,挖掘出的知识应具有事先未知、有效和可实用3个特征。
空间数据挖掘技术需要综合数据挖掘技术与空间数据库技术,它可用于对空间数据的理解,对空间关系和空间与非空间关系的发现、空间知识库的构造以及空间数据库的重组和查询的优化等。
2 空间数据挖掘技术的主要方法及特点
常用的空间数据挖掘技术包括:序列分析、分类分析、预测、聚类分析、关联规则分析、时间序列分析、粗集方法及云理论等。本文从挖掘任务和挖掘方法的角度,着重介绍了分类分析、聚类分析和关联规则分析三种常用的重要的方法。
2.1、分类分析
分类在数据挖掘中是一项非常重要的任务,目前在商业上应用最多。分类的目的是学会一个分类函数或分类模型(也常常称作分类器),该模型能把数据库中的数据项映射到给定类别中的某一个。分类和我们熟知的回归方法都可用于预测,两者的目的都是从历史数据纪录中自动推导出对给定数据的推广描述,从而能对未来数据进行预测。和回归方法不同的是,分类的输出是离散的类别值,而回归的输出则是连续的数值。二者常表现为一棵决策树,根据数据值从树根开始搜索,沿着数据满足的分支往上走,走到树叶就能确定类别。空间分类的规则实质是对给定数据对象集的抽象和概括,可用宏元组表示。
要构造分类器,需要有一个训练样本数据集作为输入。训练集由一组数据库记录或元组构成,每个元组是一个由特征(又称属性)值组成的特征向量,此外,训练样本还有一个类别标记。一个具体样本的形式可为:( v1, v2, …, vn; c );其中vi表示字段值,c表示类别。
分类器的构造方法有统计方法、机器学习方法、神经网络方法等等。统计方法包括贝叶斯法和非参数法(近邻学习或基于事例的学习),对应的知识表示是判别函数和原型事例。机器学习方法包括决策树法和规则归纳法,前者对应的表示为决策树或判别树,后者则一般为产生式规则。神经网络方法主要是反向传播(Back-Propagation,简称BP)算法,它的模型表示是前向反馈神经网络模型(由代表神经元的节点和代表联接权值的边组成的一种体系结构),BP算法本质上是一种非线性判别函数[3]。另外,最近又兴起了一种新的方法:粗糙集(rough set),其知识表示是产生式规则。
不同的分类器有不同的特点。有三种分类器评价或比较尺度:1) 预测准确度;2) 计算复杂度;3) 模型描述的简洁度。预测准确度是用得最多的一种比较尺度,特别是对于预测型分类任务,目前公认的方法是10番分层交叉验证法。计算复杂度依赖于具体的实现细节和硬件环境,在数据挖掘中,由于操作对象是海量的数据库,因此空间和时间的复杂度问题将是非常重要的一个环节。对于描述型的分类任务,模型描述越简洁越受欢迎。例如,采用规则归纳法表示的分类器构造法就很有用,而神经网络方法产生的结果就难以理解。
另外要注意的是,分类的效果一般和数据的特点有关。有的数据噪声大,有的有缺值, 有的分布稀疏,有的字段或属性间相关性强,有的属性是离散的而有的是连续值或混合式的。目前普遍认为不存在某种方法能适合于各种特点的数据。
分类技术在实际应用非常重要,比如:可以根据房屋的地理位置决定房屋的档次等。
2. 2 聚类分析
聚类是指根据“物以类聚”的原理,将本身没有类别的样本聚集成不同的组,并且对每一个这样的组进行描述的过程。它的目的是使得属于同一个组的样本之间应该彼此相似,而不同组的样本应足够不相似。与分类分析不同,进行聚类前并不知道将要划分成几个组和什么样的组,也不知道根据哪些空间区分规则来定义组。其目的旨在发现空间实体的属性间的函数关系,挖掘的知识用以属性名为变量的数学方程来表示。聚类方法包括统计方法、机器学习方法、神经网络方法和面向数据库的方法。基于聚类分析方法的空间数据挖掘算法包括均值近似算法[4]、CLARANS、BIRCH、DBSCAN等算法。目前,对空间数据聚类分析方法的研究是一个热点。
对于空间数据,利用聚类分析方法,可以根据地理位置以及障碍物的存在情况自动地进行区域划分。例如,根据分布在不同地理位置的ATM机的情况将居民进行区域划分,根据这一信息,可以有效地进行ATM机的设置规划,避免浪费,同时也避免失掉每一个商机。
2.3 关联规则分析
关联规则分析主要用于发现不同事件之间的关联性,即一事物发生时,另一事物也经常发生。关联分析的重点在于快速发现那些有实用价值的关联发生的事件。其主要依据是:事件发生的概率和条件概率应该符合一定的统计意义。空间关联规则的形式是X->Y[S%,C%],其中X、Y是空间或非空间谓词的集合,S%表示规则的支持度,C%表示规则的置信度。空间谓词的形式有3种:表示拓扑结构的谓词、表示空间方向的谓词和表示距离的谓词[5]。各种各样的空间谓词可以构成空间关联规则。如,距离信息(如Close_to(临近)、Far_away(远离))、拓扑关系(Intersect(交)、Overlap(重叠)、Disjoin(分离))和空间方位(如Right_of(右边)、West_of(西边))。实际上大多数算法都是利用空间数据的关联特性改进其分类算法,使得它适合于挖掘空间数据中的相关性,从而可以根据一个空间实体而确定另一个空间实体的地理位置,有利于进行空间位置查询和重建空间实体等。大致算法可描述如下:(1)根据查询要求查找相关的空间数据;(2)利用临近等原则描述空间属性和特定属性;(3)根据最小支持度原则过滤不重要的数据;(4)运用其它手段对数据进一步提纯(如OVERLAY);(5)生成关联规则。
关联规则通常可分为两种:布尔型的关联规则和多值关联规则。多值关联规则比较复杂,一种自然的想法是将它转换为布尔型关联规则,由于空间关联规则的挖掘需要在大量的空间对象中计算多种空间关系,因此其代价是很高的。—种逐步求精的挖掘优化方法可用于空间关联的分析,该方法首先用一种快速的算法粗略地对一个较大的数据集进行一次挖掘,然后在裁减过的数据集上用代价较高的算法进一步改进挖掘的质量。因为其代价非常高,所以空间的关联方法需要进一步的优化。
对于空间数据,利用关联规则分析,可以发现地理位置的关联性。例如,85%的靠近高速公路的大城镇与水相邻,或者发现通常与高尔夫球场相邻的对象是停车场等。
3 空间数据挖掘技术的研究方向
3.1 处理不同类型的数据
绝大多数数据库是关系型的,因此在关系数据库上有效地执行数据挖掘是至关重要的。但是在不同应用领域中存在各种数据和数据库,而且经常包含复杂的数据类型,例如结构数据、复杂对象、事务数据、历史数据等。由于数据类型的多样性和不同的数据挖掘目标,一个数据挖掘系统不可能处理各种数据。因此针对特定的数据类型,需要建立特定的数据挖掘系统。
3.2  数据挖掘算法的有效性和可测性
海量数据库通常有上百个属性和表及数百万个元组。GB数量级数据库已不鲜见,TB数量级数据库已经出现,高维大型数据库不仅增大了搜索空间,也增加了发现错误模式的可能性。因此必须利用领域知识降低维数,除去无关数据,从而提高算法效率。从一个大型空间数据库中抽取知识的算法必须高效、可测量,即数据挖掘算法的运行时间必须可预测,且可接受,指数和多项式复杂性的算法不具有实用价值。但当算法用有限数据为特定模型寻找适当参数时,有时也会导致物超所值,降低效率。
3.3 交互性用户界面
数据挖掘的结果应准确地描述数据挖掘的要求,并易于表达。从不同的角度考察发现的知识,并以不同形式表示,用高层次语言和图形界面表示数据挖掘要求和结果。目前许多知识发现系统和工具缺乏与用户的交互,难以有效利用领域知识。对此可以利用贝叶斯方法和演译数据库本身的演译能力发现知识。
3.4 在多抽象层上交互式挖掘知识
很难预测从数据库中会挖掘出什么样的知识,因此一个高层次的数据挖掘查询应作为进一步探询的线索。交互式挖掘使用户能交互地定义一个数据挖掘要求,深化数据挖掘过程,从不同角度灵活看待多抽象层上的数据挖掘结果。
3.5  从不同数据源挖掘信息
局域网、广域网以及Internet网将多个数据源联成一个大型分布、异构的数据库,从包含不同语义的格式化和非格式化数据中挖掘知识是对数据挖掘的一个挑战。数据挖掘可揭示大型异构数据库中存在的普通查询不能发现的知识。数据库的巨大规模、广泛分布及数据挖掘方法的计算复杂性,要求建立并行分布的数据挖掘。
3.6  私有性和安全性
数据挖掘能从不同角度、不同抽象层上看待数据,这将影响到数据挖掘的私有性和安全性。通过研究数据挖掘导致的数据非法侵入,可改进数据库安全方法,以避免信息泄漏。
3.7  和其它系统的集成
方法、功能单一的发现系统的适用范围必然受到一定的限制。要想在更广泛的领域发现知识,空间数据挖掘系统就应该是数据库、知识库、专家系统、决策支持系统、可视化工具、网络等技术的集成。
4 有待研究的问题
我们虽然在空间数据挖掘技术的研究和应用中取得了很大的成绩,但在一些理论及应用方面仍存在急需解决的问题。
4.1 数据访问的效率和可伸缩性
空间数据的复杂性和数据的大量性,TB数量级的数据库的出现,必然增大发现算法的搜索空间,增加了搜索的盲目性。如何有效的去除与任务无关的数据,降低问题的维数,设计出更加高效的挖掘算法对空间数据挖掘提出了巨大的挑战。
4.2 对当前一些GIS软件缺乏时间属性和静态存储的改进
由于数据挖掘的应用在很大的程度上涉及到时序关系,因此静态的数据存储严重妨碍了数据挖掘的应用。基于图层的计算模式、不同尺度空间数据之间的完全割裂也对空间数据挖掘设置了重重障碍。空间实体与属性数据之间的联系仅仅依赖于标识码,这种一维的连接方式无疑将丢失大量的连接信息,不能有效的表示多维和隐含的内在连接关系,这些都增加了数据挖掘计算的复杂度,极大地增加了数据准备阶段的工作量和人工干预的程度。
4.3 发现模式的精炼
当发现空间很大时会获得大量的结果,尽管有些是无关或没有意义的模式,这时可利用领域的知识进一步精炼发现的模式,从而得到有意义的知识。
在空间数据挖掘技术方面,重要的研究和应用的方向还包括:网络环境上的数据挖掘、栅格矢量一体化的挖掘、不确定性情况下的数据挖掘、分布式环境下的数据挖掘、数据挖掘查询语言和新的高效的挖掘算法等。
5  小结
随着GIS与数据挖掘及相关领域科学研究的不断发展,空间数据挖掘技术在广度和深度上的不断深入,在不久的将来,一个集成了挖掘技术的GIS、GPS、RS集成系统必将朝着智能化、网络化、全球化与大众化的方向发展。
参考文献:
[1] 邬 伦 等 地理信息系统――原理、方法和应用 .科学出版社.2001.
[2] 邸凯昌.空间数据挖掘和知识发现的理论与方法[D].武汉:武汉测绘科技大学,1999.
[3] 蔡自兴,徐光祐. 人工智能及其应用. 清华大学出版社. 1999. 206~216.
[4] Sheikholeslami G, Chatterjee S, Zhang A. Wave-Cluster: A multi-resolution clustering approach for very large spatiall databases. In:Proceedings of the 24th International Conference on Very Large Databases. New York, 1998. 428~439.
[5] 朱建秋,张晓辉,菇伟杰,朱杨勇.数据挖掘语言浅析[Z].
http://www.sqlmine.com/warehouse/htm/40.htm.
 
The Technology and Methods of Spatial Data Mining
Ge Ji-Ke
(Information College  South West Agricultural University  Chongqing  400716)
Abstract: This paper introduces the theory and characteristic of spatial database and spatial data mining, analyses the hierarchy method and knowledge’s classification of spatial data mining, introduces spatial classification rules , spatial clustering rules and spatial association rules, points out unsolved question, trend and direction.
Key words: spatial data mining, classification, clustering, association rules

2006年09月11日

窗口创建步骤:

1、设计一个窗口类

2、注册窗口类

3、创建窗口

4、显示及更新窗口–小心循环、消息处理

创建链表

1、动态分配

2、初始化新节点Next指针(NULL)

3、若为空表:头=尾=新

       若不为空:尾的Next =新

                            尾=新

 

#include<stdio.h>
struct Node
{
 int data;
 Node *next;
};
void main()
{
 Node *pHead=NULL;
 Node *pTail=NULL;
 Node *pNew=NULL;
 while(1)
 {
  pNew=new Node;    //动态分配
  pNew->next=NULL;//初始化新节点Next指针(NULL)
  
  printf("请输入数据:");
  scanf("%d",&pNew->data);
  
  if(pNew->data==0)
  {
   delete pNew;
   break;
  }
  
  if(pHead==NULL)
  {
   pHead=pTail=pNew;  //若为空表:头=尾=新
  }
  
  else
  {
   pTail->next=pNew;  //   若不为空:尾的Next =新 ;尾=新
   pTail=pNew;
  }
  
 }
 Node *pMove=pHead;
 while(pMove!=NULL)
 {
  printf("%d\t",pMove->data);
  pMove=pMove->next;
 }
 
}