功 能: 设计算法,将两个单链表数组的特定位序, 相同者,链接起来
编程人: 王涛
详细博客:https://blog.csdn.net/qq_57484399/article/details/127161982
时 间: 2024.4.14
版本更新日志:
版 本1.0日志: V1.0 基本功能
版 本2.0日志 : 增加直接数组处理 , 无需人工输入, 增加数组数据遍历
目录
V1.0
main.cpp
/*****************************************
功 能: 设计算法,将两个单链表数组的特定位序, 相同者,链接起来
编程人: 王涛
详细博客:https://blog.csdn.net/qq_57484399/article/details/127161982
时 间: 2024.4.14
版 本: V1.0
******************************************/
#include <stdio.h>
#include <malloc.h>
#define MaxCol 10
typedef int ElemType;
typedef struct dataNode
{
ElemType date[MaxCol]; //存储数据的节点数组
struct dataNode *next; //定义节点的前驱指针
}DataList;
typedef struct headNode
{
int row; //头结点数据存储链表的 行数和列数
int columns;
DataList *next; //头结点的后继指针类型是 DataList
}HeadList;
void CreatTable(HeadList *&new_table)
{
int i,j;
DataList *tailNode; //尾指针节点
DataList *dataNode; //数据新节点
new_table = (HeadList*)malloc(sizeof(HeadList));
new_table->next = NULL;//基本头结点创建成功
//下面分配行列数
printf("请输入表的行数和列数:");
scanf("%d%d",&new_table->row,&new_table->columns);
//头结点基本创建完成
//下面遍历输入数据节点
for(i = 0;i < new_table->row; i++)
{
printf("请输入第%d行的数据:",i+1);
//为每行数组分配空间
dataNode = (DataList*)malloc(sizeof(DataList));
for(j = 0;j < new_table->columns; j++)
{
scanf("%d",&dataNode->date[j]);
}
//数据填充完毕, 开始 尾插法插入头结点之后(head和data节点类型不一致,区分插入)
if(new_table->next == NULL)
{
new_table->next = dataNode;
}
else
{
tailNode->next = dataNode;
}
tailNode = dataNode; //尾结点指向新节点
}
//尾指针置空
tailNode->next = NULL;
}
/*****************************************
//定义指针指向数据节点
//while(数据节点不为空){
//()for循环遍历数组
//遍历完指针后移
//}
//记得换行回车
******************************************/
void DisplayTable(HeadList *showTable)
{
int i;
//定义指针指向数据节点
dataNode *nowNode = showTable->next;
//while(数据节点不为空){
printf("\n");
while(nowNode != NULL)
{
//()for循环遍历数组
for(i = 0; i < showTable->columns; i++)
{
printf("%2d",nowNode->date[i]);
printf(" ");
}
//记得换行回车
printf("\n");
printf("\n");
//遍历完指针后移
nowNode = nowNode->next;
}
}
void LinkTable(HeadList *first_table,HeadList *second_table,HeadList *&result_table)
{
DataList *firstNode;
DataList *secondNode;
DataList *newNode;
DataList *tailNode;
int connect_table1,connect_table2;
int serial_number; //数组序号
//result_table 头节点建立好 (列 = first_table->columns + second_table->columns),行不确定
result_table = (HeadList*)malloc(sizeof(HeadList));
result_table->columns = first_table->columns + second_table->columns;
result_table->row = 0; //目前是0
//然后头结点next置空
result_table->next = NULL;
//while 遍历 first_table每个节点 ,
firstNode = first_table->next;
secondNode = second_table->next;
printf("表1连接的数组位序:");
scanf("%d",&connect_table1);
getchar();getchar();
printf("表2连接的数组位序:");
scanf("%d",&connect_table2);
while(firstNode != NULL)
{
secondNode = second_table->next;//每次都重新遍历
//拿first_table一个节点 遍历 second_table的所有节点
while(secondNode != NULL)
{
//判断特定行,特定列, 相等,则链接相关数组for循环
if(secondNode->date[connect_table2-1] == firstNode->date[connect_table1-1])
{
newNode = (DataList*)malloc(sizeof(DataList));
//连接两数组(first先, second后)
for(serial_number = 0; serial_number < first_table->columns;serial_number++)
{
newNode->date[serial_number] = firstNode->date[serial_number];
}
for(serial_number = 0;serial_number < second_table->columns;serial_number++)
{
newNode->date[(first_table->columns)+serial_number] = secondNode->date[serial_number];
}
if(result_table->next == NULL)
{
result_table->next = newNode;
}
else
{
tailNode->next = newNode;
}
tailNode = newNode;
result_table->row++;
//尾插法插入result_table后
}
secondNode = secondNode->next;
}
firstNode = firstNode->next;
}
//result_table尾结点 置空
tailNode->next = NULL;
}
int main()
{
HeadList *first_table; //代表要处理第一个表
HeadList *second_table; //代表第要处理二个表
HeadList *result_table; //两个表处理后,存储结果的表C
printf("表1:\n");
//用头结点建表
CreatTable(first_table);
printf("表2:\n");
//头结点建表
CreatTable(second_table);
//处理两个表
LinkTable(first_table,second_table,result_table);
DisplayTable(result_table);
return 0;
}
v1.0运行结果:
V2.0
更新功能
方便手打数组:
ElemType first[5][3] = { {3,2,3}, {2,1,2}, {4,2,4}, {1,1,2}, {5,2,1}, }; ElemType second[4][2] = { {2,1}, {1,2}, {5,3}, {2,4}, };
增加的功能: 计算 所写数组的 行,列, 并把数组填充到指针数组里面 , 方便弹性传入函数
ephemeral_row = sizeof(first)/sizeof(first[0]); ephemeral_columns = sizeof(first[0])/sizeof(first[0][0]); ElemType **Array_use = (ElemType **)malloc(ephemeral_row*sizeof(ElemType*)); for(int i = 0; i < ephemeral_row; i++) { Array_use[i] = (ElemType *)malloc(ephemeral_columns *sizeof(ElemType)); //填充数据 for(int j = 0; j < ephemeral_columns; j++) { Array_use[i][j] = first[i][j]; } } CreatTable_auto(first_table,Array_use,ephemeral_row,ephemeral_columns);
计算行列数: 您已经使用了
sizeof
运算符来计算数组的行数和列数,这是正确的。这里是您的代码:ephemeral_row = sizeof(first) / sizeof(first[0]); ephemeral_columns = sizeof(first[0]) / sizeof(first[0][0]);
创建
CreatTable_auto
函数: 您需要修改CreatTable_auto
函数,以便它可以接受一个指向指针的指针作为参数,这样就可以传入任意大小的二维数组。这里是修改后的函数原型:void CreatTable_auto(HeadList *&new_table, ElemType **Array_use, int row, int columns);
动态分配二维数组: 在调用
CreatTable_auto
之前,您需要动态创建一个二维数组。这里是如何做到这一点的示例代码:// 分配行指针 ElemType **Array_use = (ElemType **)malloc(ephemeral_row * sizeof(ElemType *)); for (int i = 0; i < ephemeral_row; i++) { // 为每一行分配列 Array_use[i] = (ElemType *)malloc(ephemeral_columns * sizeof(ElemType)); // 填充数据 for (int j = 0; j < ephemeral_columns; j++) { Array_use[i][j] = first[i][j]; } }
空间分配:
解析:
在C语言中,当您使用
malloc
动态分配内存来创建一个二维数组时,内存的摆放方式如下:
行指针数组: 首先,您分配了一个行指针数组。这个数组包含了指向每一行的指针。这些指针是有序的,按照您分配它们的顺序排列。例如,
Array_use[0]
将指向第一行,Array_use[1]
将指向第二行,依此类推。行内存分配: 对于每一行,您又分配了一个数组来存储实际的数据。这些数据数组也是有序的,每个数组对应于行指针数组中的一个指针。
这种内存摆放方式可以用以下图示表示:
Array_use --> [ Ptr_Row0 | Ptr_Row1 | Ptr_Row2 | ... | Ptr_RowN ] | | | | v v v v [Data_Row0] [Data_Row1] [Data_Row2] ... [Data_RowN]
每个
Ptr_RowX
是一个指针,指向一个Data_RowX
,这是一个包含行数据的数组。当您需要访问这些行地址时,您可以直接通过行指针数组进行索引。例如,如果您想访问第
i
行的第j
个元素,您可以使用Array_use[i][j]
。这是因为Array_use[i]
给出了第i
行的起始地址,而[j]
给出了从该行起始地址开始的第j
个元素的偏移量。请注意,虽然这些行指针是连续存储的,但每一行的数据可能不是连续存储的。每一行都是单独分配的,所以它们在内存中的位置可能是分散的。
建表函数:
void CreatTable_auto(HeadList *&new_table,ElemType **Array_use,int row,int columns) { int i,j; DataList *tailNode; //尾指针节点 DataList *dataNode; //数据新节点 new_table = (HeadList*)malloc(sizeof(HeadList)); new_table->next = NULL;//基本头结点创建成功 //下面分配行列数 //计算行数 new_table->row = row;//计算行数 new_table->columns = columns;//计算行数 //头结点基本创建完成 //下面遍历输入数据节点 for(i = 0;i < new_table->row; i++) { // printf("请输入第%d行的数据:",i+1); //为每行数组分配空间 dataNode = (DataList*)malloc(sizeof(DataList)); for(j = 0;j < new_table->columns; j++) { // scanf("%d",&dataNode->date[j]); dataNode->date[j] = Array_use[i][j]; } //数据填充完毕, 开始 尾插法插入头结点之后(head和data节点类型不一致,区分插入) if(new_table->next == NULL) { new_table->next = dataNode; } else { tailNode->next = dataNode; } tailNode = dataNode; //尾结点指向新节点 } //尾指针置空 tailNode->next = NULL; }
解析: 因为使用的是 数组指针, 所以可以弹性访问数组内数据, 不在在意不同行和列
main.cpp
/*****************************************
功 能: 设计算法,将两个单链表数组的特定位序, 相同者,链接起来
编程人: 王涛
详细博客:https://blog.csdn.net/qq_57484399/article/details/127161982
时 间: 2024.4.14
v2.0日志:增设非交互模式
版 本: V2.0
******************************************/
#include <stdio.h>
#include <malloc.h>
#define MaxCol 10
typedef int ElemType;
typedef struct dataNode
{
ElemType date[MaxCol]; //存储数据的节点数组
struct dataNode *next; //定义节点的前驱指针
}DataList;
typedef struct headNode
{
int row; //头结点数据存储链表的 行数和列数
int columns;
DataList *next; //头结点的后继指针类型是 DataList
}HeadList;
ElemType first[5][3] = {
{3,2,3},
{2,1,2},
{4,2,4},
{1,1,2},
{5,2,1},
};
ElemType second[4][2] = {
{2,1},
{1,2},
{5,3},
{2,4},
};
void CreatTable(HeadList *&new_table)
{
int i,j;
DataList *tailNode; //尾指针节点
DataList *dataNode; //数据新节点
new_table = (HeadList*)malloc(sizeof(HeadList));
new_table->next = NULL;//基本头结点创建成功
//下面分配行列数
printf("请输入表的行数和列数:");
scanf("%d%d",&new_table->row,&new_table->columns);
//头结点基本创建完成
//下面遍历输入数据节点
for(i = 0;i < new_table->row; i++)
{
printf("请输入第%d行的数据:",i+1);
//为每行数组分配空间
dataNode = (DataList*)malloc(sizeof(DataList));
for(j = 0;j < new_table->columns; j++)
{
scanf("%d",&dataNode->date[j]);
}
//数据填充完毕, 开始 尾插法插入头结点之后(head和data节点类型不一致,区分插入)
if(new_table->next == NULL)
{
new_table->next = dataNode;
}
else
{
tailNode->next = dataNode;
}
tailNode = dataNode; //尾结点指向新节点
}
//尾指针置空
tailNode->next = NULL;
}
void CreatTable_auto(HeadList *&new_table,ElemType **Array_use,int row,int columns)
{
int i,j;
DataList *tailNode; //尾指针节点
DataList *dataNode; //数据新节点
new_table = (HeadList*)malloc(sizeof(HeadList));
new_table->next = NULL;//基本头结点创建成功
//下面分配行列数
//计算行数
new_table->row = row;//计算行数
new_table->columns = columns;//计算行数
//头结点基本创建完成
//下面遍历输入数据节点
for(i = 0;i < new_table->row; i++)
{
// printf("请输入第%d行的数据:",i+1);
//为每行数组分配空间
dataNode = (DataList*)malloc(sizeof(DataList));
for(j = 0;j < new_table->columns; j++)
{
// scanf("%d",&dataNode->date[j]);
dataNode->date[j] = Array_use[i][j];
}
//数据填充完毕, 开始 尾插法插入头结点之后(head和data节点类型不一致,区分插入)
if(new_table->next == NULL)
{
new_table->next = dataNode;
}
else
{
tailNode->next = dataNode;
}
tailNode = dataNode; //尾结点指向新节点
}
//尾指针置空
tailNode->next = NULL;
}
/*****************************************
//定义指针指向数据节点
//while(数据节点不为空){
//()for循环遍历数组
//遍历完指针后移
//}
//记得换行回车
******************************************/
void DisplayTable(HeadList *showTable)
{
int i;
//定义指针指向数据节点
dataNode *nowNode = showTable->next;
//while(数据节点不为空){
printf("\n");
while(nowNode != NULL)
{
//()for循环遍历数组
for(i = 0; i < showTable->columns; i++)
{
printf("%2d",nowNode->date[i]);
printf(" ");
}
//记得换行回车
printf("\n");
printf("\n");
//遍历完指针后移
nowNode = nowNode->next;
}
}
void LinkTable(HeadList *first_table,HeadList *second_table,HeadList *&result_table)
{
DataList *firstNode;
DataList *secondNode;
DataList *newNode;
DataList *tailNode;
int connect_table1,connect_table2;
int serial_number; //数组序号
//result_table 头节点建立好 (列 = first_table->columns + second_table->columns),行不确定
result_table = (HeadList*)malloc(sizeof(HeadList));
result_table->columns = first_table->columns + second_table->columns;
result_table->row = 0; //目前是0
//然后头结点next置空
result_table->next = NULL;
//while 遍历 first_table每个节点 ,
firstNode = first_table->next;
secondNode = second_table->next;
printf("表1连接的数组位序:");
scanf("%d",&connect_table1);
printf("表2连接的数组位序:");
scanf("%d",&connect_table2);
while(firstNode != NULL)
{
secondNode = second_table->next;//每次都重新遍历
//拿first_table一个节点 遍历 second_table的所有节点
while(secondNode != NULL)
{
//判断特定行,特定列, 相等,则链接相关数组for循环
if(secondNode->date[connect_table2-1] == firstNode->date[connect_table1-1])
{
newNode = (DataList*)malloc(sizeof(DataList));
//连接两数组(first先, second后)
for(serial_number = 0; serial_number < first_table->columns;serial_number++)
{
newNode->date[serial_number] = firstNode->date[serial_number];
}
for(serial_number = 0;serial_number < second_table->columns;serial_number++)
{
newNode->date[(first_table->columns)+serial_number] = secondNode->date[serial_number];
}
if(result_table->next == NULL)
{
result_table->next = newNode;
}
else
{
tailNode->next = newNode;
}
tailNode = newNode;
result_table->row++;
//尾插法插入result_table后
}
secondNode = secondNode->next;
}
firstNode = firstNode->next;
}
//result_table尾结点 置空
tailNode->next = NULL;
}
int main()
{
HeadList *first_table; //代表要处理第一个表
HeadList *second_table; //代表第要处理二个表
HeadList *result_table; //两个表处理后,存储结果的表C
int ephemeral_row;
int ephemeral_columns;
int mode;
printf("请问您需要交互式,还是 直接处理数据呢? 1:交互 2:手写数组\n\n");
scanf("%d",&mode);
if(mode == 1)
{
printf("表1:\n");
//用头结点建表
CreatTable(first_table);
printf("表2:\n");
//头结点建表
CreatTable(second_table);
}
else if(mode == 2)
{
ephemeral_row = sizeof(first)/sizeof(first[0]);
ephemeral_columns = sizeof(first[0])/sizeof(first[0][0]);
ElemType **Array_use = (ElemType **)malloc(ephemeral_row*sizeof(ElemType*));
for(int i = 0; i < ephemeral_row; i++)
{
Array_use[i] = (ElemType *)malloc(ephemeral_columns *sizeof(ElemType));
//填充数据
for(int j = 0; j < ephemeral_columns; j++)
{
Array_use[i][j] = first[i][j];
}
}
CreatTable_auto(first_table,Array_use,ephemeral_row,ephemeral_columns);
DisplayTable(first_table);
ephemeral_row = sizeof(second)/sizeof(second[0]);
ephemeral_columns = sizeof(second[0])/sizeof(second[0][0]);
ElemType **Array_use1 = (ElemType **)malloc(ephemeral_row*sizeof(ElemType*));
for(int i = 0; i < ephemeral_row; i++)
{
Array_use1[i] = (ElemType *)malloc(ephemeral_columns *sizeof(ElemType));
//填充数据
for(int j = 0; j < ephemeral_columns; j++)
{
Array_use1[i][j] = second[i][j];
}
}
CreatTable_auto(second_table,Array_use1,ephemeral_row,ephemeral_columns);
DisplayTable(second_table);
}
//处理两个表
LinkTable(first_table,second_table,result_table);
printf("处理完后:\n\n");
DisplayTable(result_table);
return 0;
}