在学习链表后发现链表的连续性,节省空间之后写了一个学生管理表的小项目 独立思考了如何删除结点(代码中是将结点跳过却没有释放结点的空间),如何增加结点与修改选中结点。
代码作为练习代码。
没有更加的精简 可能会给你在链表学习上 提供一些一些参考思路。
int main()
{
Node* hand;
init();
return 0;
}
void menu()
{
printf("*****************************************\n");
printf("**************1增加学生档案**************\n");
printf("**************2删除对应档案**************\n");
printf("**************3查看**********************\n");
printf("**************4更改代码******************\n");
printf("*****************************************\n");
}
建立动态链表与增加结点 *** 作
在代码的主题上运用里分支语句switch语句和循环语句do while语句来进行
单链表的建立运用一个新结点和一个对为节点来配合建立。
每次选择增加档案后会再次给 pnew新结点分配空间 然后直接 在尾节点pend原有基础上连接
(在这里将建立链表的内容自己建立一个函数来进行 代码结构会简洁不少)
最后将不需要的penw结点释放
int c; //选择 存储
int j; //后续 判断是否再次进行更改 *** 作的 变量
Node* hand;
Node* pnew, * pend;
hand = NULL;
pend = (Node*)malloc(sizeof(Node));//先分配队尾结点 队尾结点只要初始化一次就可以 后续新结点不断地将地址赋给队尾结点
do {
menu();
printf("请选择要进行的 *** 作\n");
scanf("%d", &c);// *** 作选择
switch (c)
{
case 1:
while (1)
{
pnew = (Node*)malloc(sizeof(Node)); //分配新结点的地址
printf("请输入第%d个学生的信息: 学号:", icount + 1);
scanf("%d", &pnew->Nu);
if (pnew->Nu == 0)
break;
printf(" 姓名:", icount + 1);
scanf("%s", &pnew->student);
icount++;
pnew->nu = icount;//初始化序号
if (icount == 1)
{
pnew->next = NULL;
hand = pnew;
pend = pnew;
}
else
{
pnew->next = NULL;
pend->next = pnew;
pend = pnew;
}
pnew = (Node*)malloc(sizeof(Node)); //再次分配新结点地址
}
free(pnew);//释放不需要的结点;
print(hand);
break;
删除数据 *** 作
这里的代码是跳过 *** 作并不是真正意义上的删除 *** 作
这里的 *** 作分为三种 删除第一个数据、中间的数据和最后的数据
三种结点的情况不一样
头节点的话直接将第二个结点的地址付给第一个之后 返回 即可
中间 遍历链表找到要删除数据的前一个和后一个 进行连接
队尾 找到前一个结点将 p->next变为NULL;
case 2:
hand=Delete(hand);//删除结点
icount=resort(hand);//排序之后返回结点长度 为了后续再增加 结点时的 *** 作
print(hand);
break;
Node* Delete(Node* p) //删除
{
print(p);
int n = 0;
Node* pc;
pc = p;
printf("请选择要删除信息的序号\n");
scanf("%d", &n);
if (n == 1)//若删除第一个结点的判断
{
pc = p->next;
return pc;
}
else {
while (p->nu != n - 1)//找到要删除结点的上一结点
{
p = p->next;
}
Node* pa, * pb;//建立中间变量 接受前结点和后结点
pa = p;
p = p->next;//p此时为被删除的结点
if (p->next == NULL)// 若删除最后一个结点的判断
{
pa->next = NULL;
return pc;
}
else
{
pb = p->next;//pb为被删除结点的下一结点
pa->next = pb;
return pc;
}
}
}
这里遍历链表的和寻找前后结点的 *** 作是在定义结构体时 在内放置了一个序号变量
但是删除 *** 作进行之后 序号会缺失 这就要再次给序号赋值 而且链表的长度也会有变化 所以也需要一个变量来保存长度 这一步直接在赋值序号时一并进行
int resort(Node* p)//给删减后的结点重新标序号
{
int n = 1;
while (p != NULL)
{
p->nu = n;
n++;
p = p->next;
}
return n - 1;
}
更改结点内容
这一步是最简单的一部 只需要找到结点位置 之后更改就可以了
void Change(Node* p)
{
int n;
printf("请输入想更改档案的序号\n");
scanf("%d", &n);//
while (p->nu != n)//遍历链表寻找结点
{
p = p->next;
}
printf("请输入更改后的信息\n");
printf("学号:");
scanf("%d", &p->Nu);
printf("姓名:");
scanf("%s", &p->student);
printf("修改完成!");
}
结尾:
#include
#include
int icount = 0;
typedef struct Node
{
int nu;
char student[20];
int Nu;
struct Node* next;
}Node;
void menu()
{
printf("*****************************************\n");
printf("**************1增加学生档案**************\n");
printf("**************2删除对应档案**************\n");
printf("**************3查看**********************\n");
printf("**************4更改代码******************\n");
printf("*****************************************\n");
}
void print(Node* hand)
{
printf(" 学生档案表\n");
printf("序号 学号 姓名\n");
while (hand != NULL)//再循环输出的时候 要注意hand的已经是下一个结点了
{
printf(" %d %d %s\n",hand->nu, hand->Nu, hand->student);
printf("\n");
hand = hand->next;
}
}
Node* Delete(Node* p) //删除
{
print(p);
int n = 0;
Node* pc;
pc = p;
printf("请选择要删除信息的序号\n");
scanf("%d", &n);
if (n == 1)//若删除第一个结点的判断
{
pc = p->next;
return pc;
}
else {
while (p->nu != n - 1)//找到要删除结点的上一结点
{
p = p->next;
}
Node* pa, * pb;//建立中间变量 接受前结点和后结点
pa = p;
p = p->next;//p此时为被删除的结点
if (p->next == NULL)// 若删除最后一个结点的判断
{
pa->next = NULL;
return pc;
}
else
{
pb = p->next;//pb为被删除结点的下一结点
pa->next = pb;
return pc;
}
}
}
void Change(Node* p)
{
int n;
printf("请输入想更改档案的序号\n");
scanf("%d", &n);//
while (p->nu != n)//遍历链表寻找结点
{
p = p->next;
}
printf("请输入更改后的信息\n");
printf("学号:");
scanf("%d", &p->Nu);
printf("姓名:");
scanf("%s", &p->student);
printf("修改完成!");
}
int resort(Node* p)//给删减后的结点重新标序号
{
int n = 1;
while (p != NULL)
{
p->nu = n;
n++;
p = p->next;
}
return n - 1;
}
void init()
{
int c; //选择 存储
int j; //后续 判断是否再次进行更改 *** 作的 变量
Node* hand;
Node* pnew, * pend;
hand = NULL;
pend = (Node*)malloc(sizeof(Node));//先分配队尾结点 队尾结点只要初始化一次就可以 后续新结点不断地将地址赋给队尾结点
do {
menu();
printf("请选择要进行的 *** 作\n");
scanf("%d", &c);// *** 作选择
switch (c)
{
case 1:
while (1)
{
pnew = (Node*)malloc(sizeof(Node)); //分配新结点的地址
printf("请输入第%d个学生的信息: 学号:", icount + 1);
scanf("%d", &pnew->Nu);
if (pnew->Nu == 0)
break;
printf(" 姓名:", icount + 1);
scanf("%s", &pnew->student);
icount++;
pnew->nu = icount;//初始化序号
if (icount == 1)
{
pnew->next = NULL;
hand = pnew;
pend = pnew;
}
else
{
pnew->next = NULL;
pend->next = pnew;
pend = pnew;
}
pnew = (Node*)malloc(sizeof(Node)); //再次分配新结点地址
}
free(pnew);//释放不需要的结点;
print(hand);
break;
case 2:
hand=Delete(hand);//删除结点
icount=resort(hand);//排序之后返回结点长度 为了后续再增加 结点时的 *** 作
print(hand);
break;
case 3:
print(hand);
break;
case 4:
do {
Change(hand);
printf("修改后的表为\n");
print(hand);
printf("是否继续修改?(1/0)\n");
scanf("%d",&j);
} while (j);
break;
default:
printf("!!!未知 *** 作数!!!请重新输入\n");
break;
}
} while (c);
}
int main()
{
Node* hand;
init();
return 0;
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)