[数据结构]练习2-不带头结点的单链表

实验一


/*编写函数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;
  }
}
  • 11
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值