问题描述:把两个表按照某个规则连接起来。
比如说有两个个表
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;
}