实验一
/*编写函数slnklist delx(linklist head, datatype x),删除不带头结点单链表head中第一个值为x 的结点。
并构造测试用例进行测试。
*/
/**********************************/
/*文件名称:lab2_01.c */
/**********************************/
#include "slnklist.h"
/*请将本函数补充完整,并进行测试*/
linklist delx(linklist head,datatype x)
{
node *pre=NULL,*p;//初始化
if(head==NULL){
printf("链表是空的");//判断不为空
return head;
}else{
p=head; //p从头开始 查找
while(p&&p->info!=x){
pre=p;
p=p->next;
}
if(p!=NULL){//不是不为0是不为空
if(pre!=NULL){
pre->next=p->next;
}
else{
head=head->next;//是head不是p,p在变
}
free(p);//记得释放空间
}
return head;
}
}
int main()
{ datatype x;
linklist head;
head=creatbyqueue(); /*尾插入法建立单链表*/
print(head);
printf("请输入要删除的值:");
scanf("%d",&x);
head=delx(head,x); /*删除单链表的第一个值为x的结点*/
print(head);
delList(head); /*释放单链表空间*/
return 0;
}
总结
删除值为x的结点,首先判断链表是否为空,然后进行寻找值为x的结点,在找到后进行判断链首还是链表中间,结点前驱直接指向要删除结点的下一结点,最后释放被删除的结点。要记得返回链表的头指针!!
初始化中,p=head,pre一定记得赋值为NULL
实验二
/**********************************/
/*文件名称:lab2_02.c */
/**********************************/
/*
假设线性表(a1,a2,a3,…an)采用不带头结点的单链表存储,
请设计算法函数linklist reverse1(linklist head)和
void reverse2(linklist *head)将不带头结点的单链表head就地倒置,
使表变成(an,an-1,…a3.a2,a1)。并构造测试用例进行测试。
*/
#include "slnklist.h"
/*请将本函数补充完整,并进行测试*/
linklist reverse1(linklist head)
{
node *s,*p;
// if(head==NULL){
// printf("链表为空!");
// return head;
// }
p=head;//从第一个结点开始
head=NULL; //还没有输入,所以链表头为空 ????????????为什么 因为这就是单纯的赋值,不是什么地址传递
while(p){
s=p;//s保留p的数据 不是p=s
p=p->next;
s->next=head;//头插法
head=s;
}
return head;
}
void reverse2(linklist *head)//node **head 指向*head的指针
{
linklist p,s;
p=*head;
*head=NULL;//初始化
while (p){
s=p;//s存储p的数据
p=p->next;
s->next=*head;//头插
*head=s;//重新生成链表
}
}
int main()
{ datatype x;
linklist head;
head=creatbystack(); /*头插入法建立单链表*/
print(head); /*输出原链表*/
head= reverse1(head); /*倒置单链表*/
print(head); /*输出倒置后的链表*/
reverse2(&head); /*倒置单链表*/
print(head);
delList(head);
return 0;
}
总结
单链表倒置:head赋值给p,因为链表没数据,head置空,进行头插法使链表倒置。若main函数里面传入的是地址,调用时需要指向该指针的指针
实验三
/*
假设不带头结点的单链表head是升序排列的,设计算法函数linklist insert(linklist head,datatype x),
将值为x的结点插入到链表head中,并保持链表有序性。
分别构造插入到表头、表中和表尾三种情况的测试用例进行测试。
*/
/**********************************/
/*文件名称:lab2_03.c */
/**********************************/
#include "slnklist.h"
/*请将本函数补充完整,并进行测试*/
linklist insert(linklist head ,datatype x)
{
linklist s,p,pre;
p=head;
while(p && p->info<x){//往下走 p->next<x不是数值,记得判断p不为空
pre=p;
p=p->next;
}
s=(linklist)malloc(sizeof(node)) ;//分配内存
s->info=x;//赋值
if(pre==NULL){
s->next=head;
head=s;
}else{
s->next=pre->next;
pre->next=s;//不是把s赋值给pre而是pre下一结点指向s
}
return head;
}
int main()
{ datatype x;
linklist head;
printf("输入一组升序排列的整数:\n");
head=creatbyqueue(); /*尾插入法建立单链表*/
print(head);
printf("请输入要插入的值:");
scanf("%d",&x);
head=insert(head,x); /*将输入的值插入到单链表适当位置*/
print(head);
delList(head);
return 0;
}
总结
将x插入有序head中使其有序。先循环 找到插入点,然后判断是头插还是中间插
实验四
/*
编写算法函数linklist delallx(linklist head, int x),删除不带头结点单链表head中所有值为x的结点。
*/
/**********************************/
/*文件名称:lab2_04.c */
/**********************************/
#include "slnklist.h"
/*请将本函数补充完整,并进行测试*/
linklist delallx(linklist head,int x)
{
linklist p,pre,s;
int i;
p=head;
// while(p){//数有几个相同的数
// if(p->info==x){
// i++;
// }
// pre=p;
// p=p->next;
// }
while(p){//遍历所有
while(p&&p->info!=x){
pre=p;//往下走寻找
p=p->next;
}
if(p){
if(pre==NULL){
head=p->next;//s->next=p->next是错的,有结点才有head->next
free(p) ;
p=head;//回到后继结点
}
else{
pre->next=p->next;
free(p);
p=pre->next;//回到后继结点
}
}
}
return head;
}
int main()
{ datatype x;
linklist head;
head=creatbyqueue(); /*尾插入法建立单链表*/
print(head);
printf("请输入要删除的值:");
scanf("%d",&x);
head=delallx(head,x);
print(head);
delList(head);
return 0;
}
总结
删除某一链表里值为x的全部数,先建立一个大循环,保证链表从头走到尾,在链表往后走的时候判断是否为值,一种是头为x,一种是中间为x,最后记住记住!!!!删除后要回到前一个结点,即重新给删除了的数赋值
slinklist.h
#include <stdio.h>
#include <stdlib.h>
/**************************************/
/* 链表实现的头文件,文件名slnklist.h */
/**************************************/
typedef int datatype;
typedef struct link_node{
datatype info;
struct link_node *next;
}node;
typedef node *linklist;
/**********************************/
/*函数名称:creatbystack() */
/*函数功能:头插法建立单链表 */
/**********************************/
linklist creatbystack()
{ linklist head,s;
datatype x;
head=NULL;
printf("请输入若干整数序列:\n");
scanf("%d",&x);
while (x!=0) /*以0结束输入*/
{ s=(linklist)malloc(sizeof(node)); /*生成待插入结点*/
s->info=x;
s->next=head; /*将新结点插入到链表最前面*/
head=s;
scanf("%d",&x);
}
return head; /*返回建立的单链表*/
}
/**********************************/
/*函数名称:creatbyqueue() */
/*函数功能:尾插法建立单链表 */
/**********************************/
linklist creatbyqueue()
{
linklist head,r,s;
datatype x;
head=r=NULL;
printf("请输入若干整数序列:\n");
scanf("%d",&x);
while (x!=0) /*以0结束输入*/
{ s=(linklist)malloc(sizeof(node));
s->info=x;
if (head==NULL) /*将新结点插入到链表最后面*/
head=s;
else
r->next=s;
r=s;
scanf("%d",&x);
}
if (r) r->next=NULL;
return head; /*返回建立的单链表*/
}
/**********************************/
/*函数名称:print() */
/*函数功能:输出不带头结点的单链表 */
/**********************************/
void print(linklist head)
{ linklist p;
int i=0;
p=head;
printf("List is:\n");
while(p)
{
printf("%5d",p->info);
p=p->next;
i++;
if (i%10==0) printf("\n");
}
printf("\n");
}
/**********************************/
/*函数名称:delList() */
/*函数功能:释放不带头结点的单链表 */
/**********************************/
void delList(linklist head)
{ linklist p=head;
while (p)
{ head=p->next;
free(p);
p=head;
}
}
实验五
/*编写函数void delx(linklist head, datatype x),删除带头结点单链表head中第一个值为x 的结点。
并构造测试用例进行测试。
*/
/**********************************/
/*文件名称:lab3_01.c */
/**********************************/
#include "slnklist.h"
/*请将本函数补充完整,并进行测试*/
void delx(linklist head,datatype x)
{
linklist p,pre,s;
pre=head;//初始化
p=head->next;//初始化 head在前,head指向 某个数,但head不会变化
while(p&&p->info!=x){
pre=p;
p=p->next;
}
// if(pre==NULL){ 这俩可以合并了
// s=head;
// s->next=p->next;
// free(p);
// }else{
// pre->next=p->next;
// free(p);
// }
if(p){
pre->next=p->next;
free(p);
}
return head;
}
int main()
{ datatype x;
linklist head;
head=creatbyqueue(); /*尾插入法建立带头结点的单链表*/
print(head);
printf("请输入要删除的值:");
scanf("%d",&x);
delx(head,x); /*删除单链表的第一个值为x的结点*/
print(head);
delList(head); /*释放单链表空间*/
return 0;
}
总结
头结点删除中,由于多了一个空结点,可以分别把head和head->next赋值给
pre和p。开始寻找x。注意这时候就不分删除的是头单元和中间单元了。
实验六
/**********************************/
/*文件名称:lab3_02.c */
/**********************************/
/*
假设线性表(a1,a2,a3,…an)采用带头结点的单链表存储,请设计算法函数void reverse(linklist head),
将带头结点的单链表head就地倒置,使表变成(an,an-1,…a3.a2,a1)。并构造测试用例进行测试。
*/
#include "slnklist.h"
/*请将本函数补充完整,并进行测试*/
void reverse(linklist head)
{
linklist p,s;
p=head->next;//赋值
head->next=NULL;
while(p){
s=p ;//保留p的数据
p=p->next;
s->next=head->next;
head->next=s;
}
return head;
}
int main()
{ datatype x;
linklist head;
head=creatbystack(); /*头插入法建立带头结点的单链表*/
print(head); /*输出原链表*/
reverse(head); /*倒置单链表*/
print(head); /*输出倒置后的链表*/
delList(head);
return 0;
}
总结
单链表倒置:head->next赋值给p,因为链表没数据,head->next置空,进行头插法使链表倒置。
slinklist.h
#include <stdio.h>
#include <stdlib.h>
/**************************************/
/* 链表实现的头文件,文件名slnklist.h */
/**************************************/
typedef int datatype;
typedef struct link_node{
datatype info;
struct link_node *next;
}node;
typedef node *linklist;
/******************************************/
/*函数名称:creatbystack() */
/*函数功能:头插法建立带头结点的单链表 */
/******************************************/
linklist creatbystack()
{
linklist head,s;
datatype x;
head=(linklist)malloc(sizeof(node));
head->next=NULL;
printf("请输入整数序列(空格分开,以0结束):\n");
scanf("%d",&x);
while (x!=0)
{
s=(linklist)malloc(sizeof(node));
s->info=x;
s->next=head->next;
head->next=s;
scanf("%d",&x);
}
return head;
}
/***************************************/
/*函数名称:creatbyqueue() */
/*函数功能:尾插法建立带头结点的单链表 */
/***************************************/
linklist creatbyqueue()
{
linklist head,r,s;
datatype x;
head=r=(linklist)malloc(sizeof(node));
head->next=NULL;
printf("请输入整数序列(空格分开,以0结束):\n");
scanf("%d",&x);
while (x!=0)
{
s=(linklist)malloc(sizeof(node));
s->info=x;
r->next=s;
r=s;
scanf("%d",&x);
}
r->next=NULL;
return head;
}
/**********************************/
/*函数名称:print() */
/*函数功能:输出带头结点的单链表 */
/**********************************/
void print(linklist head)
{
linklist p;
int i=0;
p=head->next;
printf("List is:\n");
while(p)
{
printf("%7d",p->info);
i++;
if (i%10==0) printf("\n");
p=p->next;
}
printf("\n");
}
/******************************************/
/*函数名称:creatLink() */
/*函数功能:从文件中读入n个数据构成单链表 */
/******************************************/
linklist creatLink(char *f, int n)
{
FILE *fp;
int i;
linklist s,head,r;
head=r=(linklist)malloc(sizeof(node));
head->next=NULL;
fp=fopen(f,"r");
if (fp==NULL)
return head;
else
{
for (i=0;i<n;i++)
{
s=(linklist)malloc(sizeof(node));
fscanf(fp,"%d",&(s->info));
r->next=s;
r=s;
}
r->next=NULL;
fclose(fp);
return head;
}
}
/*
函数名称:writetofile
函数功能:将链表内容存入文件f
*/
void writetofile(linklist head, char *f)
{
FILE *fp;
linklist p;
int i=0;
fp=fopen(f,"w");
if (fp!=NULL)
{
p=head->next;
fprintf(fp,"%s","List is:\n");
while(p)
{
fprintf(fp,"%7d",p->info);
i++;
if (i%10==0) fprintf(fp,"%c",'\n');
p=p->next;
}
fprintf(fp,"%c",'\n');
fclose(fp);
}
else printf("创建文件失败!");
}
/**********************************/
/*函数名称:delList() */
/*函数功能:释放带头结点的单链表 */
/**********************************/
void delList(linklist head)
{ linklist p=head;
while (p)
{ head=p->next;
free(p);
p=head;
}
}