数据结构学习笔记——线性表的应用,两个表的连接。

问题描述:把两个表按照某个规则连接起来。
比如说有两个个表
A=
[
[1 2 3]
[2 3 3]
[1 1 1]
],
B=
[
[3 5]
[1 6]
[3 4]
]
如果要把第A表每一行中的第三列与B表每一行中的第一列中元素相等的两个列(例如A表的第一行的第三列元素是3,它与B表的每一行中的第一列中的哪些元素相等呢?很显然是第一行的第一列和第三行的第一列)连接起来形成一个新的表,应该如何设计算法?
在这里插入图片描述
表的存储方法: 单链表。以行为一个数据域,以顺序表+指针域为一个结点。
顺序表的长度为两个表的长度之和。

单链表结点类型声明:

int maxsize = column1 + column2;
typedef int Elemtype;
typedef struct DNode
{
	Elemtype data[maxsize];
	DNode *next;
}DNode;

单链表头结点类型声明:
头结点用来存储表的行数以及列数,还有一个指向首结点的指针。

typedef struct HNode
{
	int Row,Column;
	DNode *next;//指向首结点 
}HNode; 

交互式建立表的单链表存储方法:

Node *L;
	L = (HNode *)malloc(sizeof(HNode));
	L -> next = NULL;//初始化一个表 
	int row,column;
	printf("请输入表的行数和列数:\n"); 
	scanf("%d %d", &row,&column);
	
	L -> Row = row;
	L -> Column = column;
	
	printf("请输入表的元素:\n");
	DNode *e,*r;
	
	int i,j; 
	for (i = 0; i < row; i ++)
	{
		e = (DNode *)malloc(sizeof(DNode));
		for (j = 0; j < column; j ++)
		{
			scanf("%d", &(e -> data[j]));
			
		}//输入了一行元素
		if (L -> next == NULL)
		{
			L -> next = e;
		 } 
		else
		{
			r -> next = e;
		}
		r = e;
	}
	r -> next = NULL;
	
	return L;
 } 

删除单链表:
删除的算法几乎是一样的,只是需要把头结点专门free掉。

void DestroyTable(HNode *L)
{
	DNode *pre,*p;
	pre = L -> next;
	p = pre -> next;
	while(p != NULL)
	{
		free(pre);
		pre = p;
		p = pre -> next;
	}
	free(pre);
	free(h);
}

输出单链表:

void DispTable(HList *L)
{
	int j;
	DNode *p = L -> next;
	while(p != NULL)
	{
		for (j=0; j < L -> Column; i ++)
		{
			printf("%4d", p -> data[j]);
		}
		printf("\n");
		p = p -> next;//当p指到下一个结点之后,就已经输出了一行了,所以循环结束的
		//条件是p == NULL
	}
}

两个表格的连接:

HNode* LinkTable(HNode *L1,HNode *L2)
{
	HNode *L;
	L = (HNode *)malloc(sizeof(HNode));
	L -> Column = L1 ->Column + L2 -> Column;
	L -> Row = 0;//结点初始化 
	L -> next = NULL;//这个非常重要!不设置就会跳过第一个结点的插入,
	//即跳过if(L -> next ==NULL)那一句。
	DNode *p1 = L1 -> next,*p2,*s,*r;
	
	printf("请输出连接字段:"); int i,j;
	scanf("%d %d", &i,&j); 
	while(p1 != NULL)
	{
		p2 = L2 -> next;
		while(p2 != NULL)
		{
			if (p1 -> data[i-1] ==  p2 -> data[j-1])
			{
				int k;
				s = (DNode *)malloc(sizeof(DNode));
				for ( k=0;k < L1 -> Column;k ++)
				{
					s -> data[k] = p1 -> data[k];
				}//将表L1的那一行输入到临时节点中去 
				for (k=0;k < L2 -> Column;k ++)
				{
					s -> data[L1 -> Column + k] = p2 -> data[k];
				}//将表L2的那一行输入到临时节点中去
				//临时节点创建完成 
				if (L -> next == NULL)
				{
					L -> next = s;
				 } 
				else
				{
					r -> next = s;
					r = s;
				}
				r = s;//临时节点接入总表完毕
				L -> Row ++; 
			}//符合条件的结点操作完毕 
			p2 = p2 -> next;
		}//表L2全部扫描完毕
		p1 = p1 -> next; 
	}
	r -> next = NULL;
	return L;
}

debug过程中最大的收获就是一个结点的初始化的指针域一定要设置为NULL,否则就会跳过某些只有指针域为NULL的步骤,如第一个结点的插入。
最后附上完整代码:

#include <stdio.h>
#include <malloc.h>
#define maxsize 10
//int maxsize= 10;
 
typedef int Elemtype;
typedef struct DNode
{
	Elemtype data[maxsize];
	struct DNode *next;
}DNode;
typedef struct HNode
{
	int Row,Column;
	DNode *next;//指向首结点 
}HNode; 

HNode* CreateLink()
{
	HNode *L;
	L = (HNode *)malloc(sizeof(HNode));
	L -> next = NULL;//初始化一个表 
	int row,column;
	printf("请输入表的行数和列数:\n"); 
	scanf("%d %d", &row,&column);
	
	L -> Row = row;
	//printf("1111111111\n");
	L -> Column = column;
	
	printf("请输入表的元素:\n");
	DNode *e,*r;
	
	int i,j; 
	for (i = 0; i < row; i ++)
	{
		e = (DNode *)malloc(sizeof(DNode));
		for (j = 0; j < column; j ++)
		{
			scanf("%d", &(e -> data[j]));
			
		}//输入了一行元素
		if (L -> next == NULL)
		{
			L -> next = e;
		 } 
		else
		{
			r -> next = e;
		}
		r = e;
	//	printf("%d\n", r ->data[0]);
	}
	r -> next = NULL;
	
	return L;
 } 
void DestroyTable(HNode *L)
{
	DNode *pre,*p;
	pre = L -> next;
	p = pre -> next;
	while(p != NULL)
	{
		free(pre);
		pre = p;
		p = pre -> next;
	}
	free(pre);
	free(L);
}
void DispTable(HNode *L)
{
	int j;
	DNode *p = L -> next;
	while(p != NULL)
	{
		for (j=0; j < L -> Column; j ++)
		{
			printf("%4d", p -> data[j]);
		}
		printf("\n");
		p = p -> next;
	}
}
HNode* LinkTable(HNode *L1,HNode *L2)
{
	HNode *L;
	L = (HNode *)malloc(sizeof(HNode));
	L -> Column = L1 ->Column + L2 -> Column;
	L -> Row = 0;//结点初始化 
	L -> next = NULL;
	DNode *p1 = L1 -> next,*p2,*s,*r;
	
	printf("请输出连接字段:"); int i,j;
	scanf("%d %d", &i,&j); 
	while(p1 != NULL)
	{
		p2 = L2 -> next;
		while(p2 != NULL)
		{
			if (p1 -> data[i-1] ==  p2 -> data[j-1])
			{
				int k;
				s = (DNode *)malloc(sizeof(DNode));
				for ( k=0;k < L1 -> Column;k ++)
				{
					s -> data[k] = p1 -> data[k];
				}//将表L1的那一行输入到临时节点中去 
				for (k=0;k < L2 -> Column;k ++)
				{
					s -> data[L1 -> Column + k] = p2 -> data[k];
				}//将表L2的那一行输入到临时节点中去
				//临时节点创建完成 
				if (L -> next == NULL)
				{
					L -> next = s;
				 } 
				else
				{
					r -> next = s;
					r = s;
				}
				r = s;//临时节点接入总表完毕
				L -> Row ++; 
			}//符合条件的结点操作完毕 
			p2 = p2 -> next;
		}//表L2全部扫描完毕
		p1 = p1 -> next; 
	}
	r -> next = NULL;
	return L;
}
int main()
{
	HNode *L1,*L2,*L;
	printf("表1:\n");
	L1 = CreateLink();
	printf("表2\n");
	L2 = CreateLink();
	printf("L2\n");
	DispTable(L2);
	L = LinkTable(L1,L2);
	printf("连接结果是:\n");
	DispTable(L);
	DestroyTable(L); 
	DestroyTable(L1); 
	DestroyTable(L2); 	
	return 0;
}
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值