C语言进阶-第19讲:链表应用(改造链表)
来源:互联网 发布:认字软件哪个好 编辑:程序博客网 时间:2024/06/07 07:26
任务和代码:
下面是一个建立动态链表的程序。阅读程序,然后按要求改造程序。
#include <iostream> using namespace std; #include <stdio.h>#include <malloc.h>#define N 5typedef struct NODE{ int data; //结点的数据 struct NODE *next; //指向下一结点} Node;Node *head=NULL; //将链表头定义为全局变量,以便于后面操作void make_list(); //建立链表void out_list(); //输出链表int main( ){ make_list(); out_list(); return 0;}void make_list(){ int n; Node *p; printf("输入若干正数(以0或一个负数结束)建立链表:" ); scanf("%d", &n); while(n>0) //输入若干正数建立链表,输入非正数时,建立过程结束 { p=(Node*)malloc(sizeof(Node)); //新建结点 p->data=n; p->next=head; //新建的结点指向原先的链表头 head=p; //链表头赋值为新建的节点,这样,新结点总是链表头 scanf("%d", &n); //输入下一个数,准备建立下一个结点 } return;}void out_list(){ Node *p=head; printf("链表中的数据为:\n"); while(p!=NULL) { printf("%d ", p->data); p=p->next; } printf("\n"); return;}
在上面的程序基础上定义下面的函数,实现相应的功能。
(1)编写make_list2()函数建立链表,使建立链表时,后输入的数据,将新输入的数字对应的结点放在链表末尾。若输入为3 5 2 9 4 7 0,建立的链表为:
(2)编写函数void search(int x),输出链表中是否有值为x的结点。
(3)编写函数delete_first_node(),删除链表中的第一个结点。
(4)编写函数delete_node(int x),删除结点值为x的结点。
(5)编写make_list3()函数建立链表,使建立链表时,使结点中的数据呈现升序。
(6)编写函数void insert(int x),将值为x的结点插入到由make_list3建立起来的有序链表中。
head.h
#ifndef HEAD_H_INCLUDED#define HEAD_H_INCLUDEDtypedef struct NODE{ int data; //结点的数据 struct NODE *next; //指向下一结点}Node;Node *head; //将链表头定义为全局变量,以便于后面操作void make_list(); //倒序建立链表void out_list(); //输出链表void make_list2(); //顺序建立链表void Search(int); //寻找链表中是否有x的结点void delete_first_node(); //删除链表中的第一个结点void delete_node(int); //删除含某个结点值的结点void make_list3(); //升序建立链表void Insert(int); //在有序表中插入结点#endif // HEAD_H_INCLUDED
main.c
#include <stdio.h>#include <malloc.h>#include "head.h"int main(){ int k; make_list(); out_list(); make_list2(); out_list(); printf("查找元素:"); scanf("%d",&k); Search(k); delete_first_node(); out_list(); delete_node(k); out_list(); scanf("%d",&k); make_list3(); out_list(); Insert(k); printf("添加数据%d后:\n",k); out_list(); return 0;}
make_list.c
#include <stdio.h>#include <malloc.h>#include "head.h"void make_list(){ int n; Node *p; head=NULL; printf("输入若干正数(以0或一个负数结束)建立链表:" ); scanf("%d", &n); while(n>0){ //输入若干正数建立链表,输入非正数时,建立过程结束 p=(Node*)malloc(sizeof(Node)); //新建结点 p->data=n; p->next=head; //新建的结点指向原先的链表头 head=p; //链表头赋值为新建的节点,这样,新结点总是链表头 scanf("%d", &n); //输入下一个数,准备建立下一个结点 } return;}
make_list2.c
#include <stdio.h>#include <malloc.h>#include "head.h"void make_list2(){ int n; Node *p,*q; printf("输入若干正数(以0或一个负数结束)建立链表:" ); scanf("%d", &n); if(n>0){ p=(Node*)malloc(sizeof(Node)); p->data=n; p->next=NULL; } else return; head=p; q=head; scanf("%d", &n); while(n>0){ p=(Node*)malloc(sizeof(Node)); p->data=n; p->next=NULL; q->next=p; q=p; scanf("%d", &n); }}
make_list3.c
#include <stdio.h>#include <malloc.h>#include "head.h"void make_list3(){ int n; head=NULL; printf("输入若干正数(以0或一个负数结束)建立有序链表:" ); scanf("%d", &n); while(n>0){ Insert(n); scanf("%d", &n); }}
out_list.c
#include <stdio.h>#include <malloc.h>#include "head.h"void out_list(){ Node *p=head; printf("链表中的数据为:\n"); while(p!=NULL){ printf("%d ", p->data); p=p->next; } printf("\n\n"); return;}
Search.c
#include <stdio.h>#include <malloc.h>#include "head.h"void Search(int x){ Node *p; p=head; while(p!=NULL){ if(p->data==x){ printf("链表中存在%d\n\n",x); break; } p=p->next; } if(p==NULL) printf("链表中不存在%d\n\n",x);}
delete_first_node.c
#include <stdio.h>#include <malloc.h>#include "head.h"void delete_first_node(){ Node *p; p=head; head=p->next; free(p); printf("删除首结点后的链表:\n");}
delete_node.c
#include <stdio.h>#include <malloc.h>#include "head.h"void delete_node(int x){ Node *p,*q; if (head==NULL) printf("空链表,不能删除\n"); else{ //要删除的恰是首结点(不排除连续有若干个结点值为x), while(head!=NULL&&head->data==x){ p=head; head=head->next; free(p); } if(head!=NULL){ p=head; q=p->next; while(q!=NULL){ if(q->data==x){//q就是该删除的结点 p->next=q->next; free(q); } else{ //q不该删除,继续考察下一个 p=q; } q=p->next; //总是p的下一个结点 } } } printf("删除含有%d的结点后:\n",x); return;}
Insert.c
#include <stdio.h>#include <malloc.h>#include "head.h"void Insert(int x){ Node *p,*q1=head,*q2; p=(Node*)malloc(sizeof(Node)); p->data=x; if(head==NULL){ head=p; p->next=NULL; } else if(p->data<head->data){ head=p; p->next=q1; } else{ while((q1!=NULL&&p->data>=q1->data)){ q2=q1; q1=q1->next; } p->next=q2->next; q2->next=p; }}
运行结果:
设计中遇到的问题与解决:
1)在源文件中使用全局变量,几乎不能在变量名前加类型名
PS:使用全局变量的另一注意点,多文件处理时不能给全局变量赋初值
原make_list2.c中的程序:
void make_list2(){ int n; Node *p,*q,*head=NULL; printf("输入若干正数(以0或一个负数结束)建立链表:" ); scanf("%d", &n); while(n>0){ p=(Node*)malloc(sizeof(Node)); p->data=n; p->next=NULL; if(head==NULL) head=p; else q->next=p; q=p; scanf("%d", &n); }}错因:
head在函数里被重新定义了,就成为了局部变量,而局部变量使用完是要被释放的,下一条语句的head当然就是和它同名的全局变量中的NULL
2)多文件的分段调试(预处理->条件编译)并在调试中支持多次输入对不同情形进行测试
如对删除指定元素的结点,不排除有多个结点有该元素,用多组数据进行测试:
#include <stdio.h>#include <malloc.h>#include "head.h"#define R#define Q 0int main(){ int k;#ifndef R make_list(); out_list();#endif // R do{ make_list2(); //out_list(); //printf("查找元素:"); scanf("%d",&k); //Search(k);#if Q delete_first_node(); out_list();#else delete_node(k); out_list(); }while(1);#endif#ifndef R make_list3(); out_list(); Insert(k); out_list();#endif // R return 0;}
3)使用函数的嵌套调用,优化make_list3.c
考虑到,新建有序表的过程就是在不断地插入结点,故利用函数的嵌套,将insert作为make_list3的子函数,
原make_list3.c与insert.c:
#include <stdio.h>#include <malloc.h>#include "head.h"void make_list3(){ int n; head=NULL; Node *p,*q1,*q2; printf("输入若干正数(以0或一个负数结束)建立有序链表:" ); scanf("%d", &n); while(n>0){ q1=head; p=(Node*)malloc(sizeof(Node)); p->data=n; if(head==NULL){ head=p; p->next=NULL; } else if(p->data<head->data){ head=p; p->next=q1; } else{ while((q1!=NULL&&p->data>=q1->data)){ q2=q1; q1=q1->next; } p->next=q2->next; q2->next=p; } scanf("%d", &n); }}
#include <stdio.h>#include <malloc.h>#include "head.h"void Insert(int x){ Node *p,*q1=head,*q2; p=(Node*)malloc(sizeof(Node)); p->data=x; if(p->data<head->data){ head=p; p->next=q1; } else{ while((q1!=NULL&&p->data>=q1->data)){ q2=q1; q1=q1->next; } p->next=q2->next; q2->next=p; } printf("在有序表中插入:%d\n",x);}
- C语言进阶-第19讲:链表应用(改造链表)
- C语言进阶-第19讲:链表应用(链表的合并)
- C语言进阶-第19讲:链表应用(拆分链表)
- C语言进阶-第19讲:链表应用(链表版通讯录)
- C语言进阶-第17讲:链表和数组的比较
- C语言进阶-第32讲:位运算及其应用
- C语言进阶-第15~16讲:结构体应用(学生成绩统计)
- C语言进阶-第15~16讲:结构体应用(玩转日期和时间)
- C语言进阶-第29讲:枚举类型及其应用(对称点)
- C语言及程序设计进阶例程-19 链表应用
- 进阶项目13- 改造链表
- C语言进阶-第8~10讲:预处理
- C语言进阶-第24~28讲:算法概述
- C语言进阶-第6讲:递归法问题求解(易列写递归方程)
- C语言进阶-第6讲:递归法问题求解(两数的最大公约数)
- C语言进阶-第6讲:递归法问题求解(递归求数组的最大值)
- C语言进阶-第11~13讲:结构体(含数组和函数)
- C语言进阶-第15~16讲:结构体(含指针和函数)
- Android加密
- 每天一道LeetCode-----将间隔集中有重叠的间隔合并
- centos7 下安装 nginx-1.12.2
- <不定时一题>归并排序
- 游戏制作
- C语言进阶-第19讲:链表应用(改造链表)
- nginx的负载均衡
- 常用 Git 命令清单
- AS java.util.concurrent.ExecutionException: com.android.tools.aapt2.Aapt2Exception: AAPT2(171104
- Python机器学习库sklearn自动特征选择(训练集)
- PAT
- ionis 和angularjs 购物车的代码
- 计算1*2*3*4*......*10的和
- HBuilder中的遍历添加数据+全选+删除+批量删除+更改+排序