数据结构实验 单链表

编写一个完整的程序,实现单链表的建立、插入、删除、输出等基本操作。

1)建立一个带头结点的单链表。

2)计算单链表的长度,然后输出单链表。

3)查找值为x的直接前驱结点q

4)删除值为x的结点。

5)把单向链表中元素逆置(不允许申请新的结点空间)。

6)已知单链表中元素递增有序,请写出一个高效的算法,删除表中所有值大于mink且小于maxk的元素(若表中存在这样的元素),同时释放被删结点空间,并分析你的算法的时间复杂度(注意:minkmaxk是给定的两个参变量,他们的值可以和表中的元素相同,也可以不同)。

7)同(6)的条件,试写一高效的算法,删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同),同时释放被删结点空间,并分析你的算法时间复杂度。

(8)利用(1)建立的链表,实现将其分解成两个链表,其中一个全部为奇数,另一个全部为偶数(尽量利用已知的存储空间)。

(9)在主函数中设计一个简单的菜单,分别测试上述算法。

//因为没有要求输入的链表数据的数量,所以我用-1表示输入结束。
//测试数据 1 2 3 4 5 6 -1
//测试删除相同元素的数据 2 2 3 3 4 4 5 5
#include<stdio.h>
#include<stdlib.h>
struct node
{
	int data;
	node *next;
};
node *h,*h1,*h2;
void Creatlist()//创建链表
{
	node *s,*e;
	h=(node *)malloc(sizeof(node));
	s=(node *)malloc(sizeof(node));
	h->next=s;
	printf("请输入单链表数据:     ");
	scanf("%d",&s->data);
	e=h;
	while(s->data!=-1)//用-1表示链表输入终止
	{
		e=s;
		s=(node *)malloc(sizeof(node));
		scanf("%d",&s->data);
		e->next=s;
	}
	e->next=NULL;
	return ;
}
void Printlist(node *h)//输出链表
{
	int count;
	node *s;
	s=h;
	count=0;
	while(s->next!=NULL)//先遍历一遍,用count记录链表的长度。
	{
		count++;
		s=s->next;
	}
	printf("单链表长度:           %d\n",count);
	if(count==0)
	{
		printf("链表为空!\n");
		return ;
	}
	printf("单链表数据:           ");
	s=h;
	while(s->next!=NULL)
	{
		s=s->next;
		printf("%d ",s->data);	
	}
	printf("\n");
	return ;
}
void Findlist()//查找值为x的前驱结点
{
	int x;
	node *s,*e;
	printf("请输入待查找的数值:   ");
	scanf("%d",&x);
	s=h->next;
	if(s->data==x)
	{
		printf("%d没有前驱结点!\n",x);//x为第一个结点
		return ;
	}
	e=s->next;
	while(e->data!=x&&e->next!=NULL)
	{
		s=e;
		e=s->next;
	}
	if(e->data!=x)
	{
		printf("单链表中不存在值为%d的结点!\n",x);//链表中没有x
		return ;
	}
	printf("%d的前驱结点为:        %d\n",x,s->data);
	return ;
}
void Deletlist()//删除值为x的结点,实验中没有要求,我写的时候是按链表中只有一个值为x的结点。
{
	int x;
	node *s,*e;
	printf("请输入需要删除的数值: ");
	scanf("%d",&x);
	s=h;
	e=s->next;
	while(e->data!=x&&e->next!=NULL)
	{
		s=e;
		e=s->next;
	}
	if(e->data!=x)
	{
		printf("单链表中不存在值为%d的结点!\n",x);//链表中没有值为x的结点
		return ;
	}
	s->next=e->next;
	free(e);
	return ;
}
void Inverlist()//逆置链表,将连接链表的指针方向倒转,不需要申请新的空间。
{
	node *s,*e,*r;
	s=h->next;
	e=s->next;
	if(e==NULL)
	{
		h->next=s;
		return ;
	}
	s->next=NULL;
	r=e->next;
	while(e!=NULL)
	{
		e->next=s;
		s=e;
		e=r;
		if(e==NULL)
			break;
		r=e->next;
	}
	h->next=s;
	return ;
}
void Delexylist()//删除链表中x和y之间的数字,而且要求释放内存。既然要求释放内存,那就只能遍历,我没想到什么更高效的算法,因为链表是有序的,我释放到值为y结束。
{
	int x,y;
	node *s,*e,*r;
	printf("请输入需要删除的区间   ");
	scanf("%d %d",&x,&y);
	r=h;
	s=h->next;
	while(s->data<=y&&s->next!=NULL)
	{
		e=s->next;
		if(s->data>=x)
		{
			free(s);
			r->next=e;
		}
		else
			r=s;
		s=e;
	}
	return ;
}
void DeleSamelist()//删除相同元素的结点同时释放内存空间。同样需要遍历,没有想到特别高效的算法。
{
	int temp;
	node *s,*e,*r;
	r=h;
	s=h->next;
	if(s==NULL)
		return ;
	temp=-1;
	while(s!=NULL)
	{
		e=s->next;
		if(s->data==temp)
		{
			free(s);
			r->next=e;
		}
		else
		{
			temp=s->data;
			r=s;
		}
		s=e;	
	}
	return ;
}
void Cutlist()//分拆链表。
{
	node *s,*s1,*e1,*s2,*e2;
	h1=(node *)malloc(sizeof(node));
	s1=(node *)malloc(sizeof(node));
	h2=(node *)malloc(sizeof(node));
	s2=(node *)malloc(sizeof(node));
	e1=h1;
	e1->next=NULL;
	e2=h2;
	e2->next=NULL;
	s=h->next;
	while(s!=NULL)
	{
		if(s->data%2!=0)
		{
			s1->data=s->data;
			e1->next=s1;
			e1=s1;
			e1->next=NULL;
			s1=(node *)malloc(sizeof(node));
		}
		else
		{
			s2->data=s->data;
			e2->next=s2;
			e2=s2;
			e2->next=NULL;
			s2=(node *)malloc(sizeof(node));
		}
		s=s->next;//第一次写的时候没有加上这一句,电脑直接就卡死了。。。。
	}
	Printlist(h1);
	Printlist(h2);
	return ;
}
int Opra()
{
	int T;
	printf("*****************目录******************\n");
	printf("创建一个单链表:                      1\n");
	printf("计算单链表长度并输出单链表:          2\n");
	printf("查找值为x的前驱结点:                 3\n");
	printf("删除值为x的结点:                     4\n");
	printf("把单链表中的元素逆置:                5\n");
	printf("删除单链表中值在x和y之间的元素:      6\n");
	printf("删除链表中值相同的元素:              7\n");
	printf("将链表分成两部分:                    8\n");
	printf("操作结束:                            0\n");
	printf("输入操作代号:         ");
	scanf("%d",&T);
	switch(T)
	{
		case 1:Creatlist();break;
		case 2:Printlist(h);break;
		case 3:Findlist(); break;
		case 4:Deletlist();break;
		case 5:Inverlist();break;
		case 6:Delexylist();break;
		case 7:DeleSamelist();break;
		case 8:Cutlist();break;
		case 0:return 0;
		default :printf("输入错误,请重新输入!\n");break;
	}
	return 1;
}
int main()
{
	int flag=1;
	while(1)
	{
		flag=Opra();
		if(!flag)//用flag控制是否跳出循环。
			break;
		printf("\n\n");
	}
	printf("谢谢使用!\n");
	return 0;
}	


  • 1
    点赞
  • 10
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

子在梦中曰

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值