AGNES 数据挖掘算法 C语言

数据挖掘算法之agnes。(最暴力的实现)(别看到暴力就放弃,hh)
。(来自青岛大学某学生)

自底向上的凝聚的方法。

随便一个输入样例:(8个点,最终聚成两类)
8
2
1 1
1 2
2 1
2 2
7 7
7 8
8 7
8 8

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

struct dian{
	int x;
	int y;
}d[1000];
struct zu{
	int cnt;
	double x,y;//定义中心点
	int d[500];//保存改组中的点
	struct zu *next;
}; 
//组使用带有头结点的链表来存储
int main(){
	int n,k;
	struct zu* head = (struct zu *)malloc(sizeof(zu));
	struct zu *p1,*p2,*p3,*p4,*prep4;//prep4用来记录p4的前一个节点,用来删除p4
	double minDis;//量纲为距离的平方

	p1 = head;
	printf("输入点的数量n 与最终组数k");
	scanf("%d%d",&n,&k);
	//第一次读入n个点,并且初始为每一个点都是一个组
	for(int i = 0;i < n;i++){
		scanf("%d%d",&d[i].x,&d[i].y);	
		//初始化每一簇
		p2 = (struct zu *)malloc(sizeof(zu));
		p2->d[0]=i; 
		p2->cnt=1;
		p2->x=d[i].x;
		p2->y=d[i].y;
		p1->next=p2;
		p1=p2;
	}
	//循环找出最小的距离的两个簇并合并,用p3与p4记录两个簇
	for(int it_cnt =0;it_cnt<n-k;it_cnt++){//n组数据,合并为k组,需要遍历n-k次
		minDis = (head->next->x - head->next->next->x)*(head->next->x - head->next->next->x)
		+(head->next->y - head->next->next->y)*(head->next->y - head->next->next->y);//初始最小距离的平方是前两个簇的距离
		p3 = head->next;
		prep4 = p3;//记录p4的前一个节点
		p4 = head->next->next;//初始p3,p4记录最小距离的两个簇的位置
		p1 = head->next;
		while(p1->next!=NULL){
			p2=p1->next;
			struct zu *prep2=p1;//记录p2前面的簇,方便记录prep4
			while(p2!=NULL){
				//计算距离
				double tmpdis = (p1->x - p2->x)*(p1->x - p2->x)+(p1->y - p2->y)*(p1->y - p2->y);
				if(tmpdis<minDis){//比最小距离小
					minDis = tmpdis;
					p3=p1;
					p4=p2;
					prep4=prep2;
				}
				prep2=p2;
				p2=p2->next;
			}
			p1=p1->next;
		}
		
		//一次遍历,获得距离最近的两个簇p3,p4,将p4合并到p3,删除p4.
		//合并
		for(int i=0;i<p4->cnt;i++){
			p3->d[p3->cnt]=p4->d[i];
			
			p3->cnt++;
		}
		//删除p4
		prep4->next=p4->next;
		free(p4);
		//重新计算p3的中心点
		int tempsumx=0,tempsumy=0;
		for(int i = 0 ;i< p3->cnt;i++){
			tempsumx+=d[p3->d[i]].x;
			tempsumy+=d[p3->d[i]].y;
		}
		p3->x=1.0*tempsumx/p3->cnt;
		p3->y=1.0*tempsumy/p3->cnt;

	}

	p1=head->next;
	while(p1!=NULL){
		printf("hello\n");
		for(int i =0 ;i<p1->cnt; i++){
			printf(" %d  ",p1->d[i]);
		}
		p1=p1->next;
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值