单链表的创建、计数打印、删除节点、增加节点、逆序操作与查找中间节点

单链表的创建、计数打印、删除节点、增加节点、逆序操作与查找中间节点,是上上一篇的补充,gcc调试通过。

 

#include<stdio.h>
#include<stdlib.h>  /*使用到其中的malloc和exit函数*/
#define times 4  /*用于循环次数的控制*/

static int N=4;  /*静态全局变量,用于控制单链表长度*/

typedef struct _person
{
	char name[12];
	int age;
	struct _person *next;
}stud;

stud *Create(int num)  /*创建单链表的函数,num为单链表的长度*/
{
	int i;
	stud *h,*p,*q;  /* h为头指针,指向单链表的第一个节点*/
	h=(stud*)malloc(sizeof(stud));
	if(h!=NULL)
	{
		p=h;
		for(i=0;i<num;i++)
		{
			q=(stud*)malloc(sizeof(stud));  /* q为指向新建节点的指针*/
			if(q!=NULL)
			{
				printf("依次输入第%d个人的姓名和年龄:\n",i+1);
				scanf("%s%d",q->name,&q->age);
				q->next=NULL;  /*创建新节点完毕*/
				p->next=q;
				p=q;
			}
		}
	}
	printf("\n");
	return(h);
}

stud *Delete(stud *person,int post)  /*删除单链表指定位置节点的函数*/
{
	int i;
	stud *cur,*pre;
	cur=person;

	if(0==post)  /*如果输入的值为0,则不删除任何节点*/
	{
		printf("\n注意:您决定不删除任何节点!!!\n\n");
		return(person);
	}
	else if(post>N||post<0)  /*如果输入的值大于单链表长度或者小于0,程序结束*/
	{
		printf("输入有误,程序终止。\n");
		exit(1);
	}
	else
	{
		if(1==post)  /*在单链表头部删除的情况*/
		{
			cur=cur->next;
			person->next=cur->next;
			free(cur);
		}
		else  /*在其它位置删除的情况*/
		{
			for(i=2;i<post+1;i++)  /*使pre成为要插入位置的上一位置的节点*/
			{
				cur=cur->next;
				pre=cur;
			}
			cur=cur->next;
			pre->next=cur->next;
			free(cur);
		}
		return(person);
	}
}

stud *Insert(stud *person,int post)  /*在单链表指定位置插入新的节点的函数*/
{
	int i;
	stud *cur,*pre,*node;
	
	if(post>N+1||post<1)  /*如果输入的值大于单链表长度加1或者小于1,程序结束*/
	{
		printf("输入错误,程序终止。\n");
		exit(1);
	}

	if(person!=NULL)
	{
		cur=person;
		node=(stud*)malloc(sizeof(stud));
		if(node!=NULL)
		{
			printf("请输入新人的姓名和年龄:\n");
			scanf("%s%d",node->name,&node->age);  /*为新的节点输入数据内容*/

			if(1==post)
			{
				node->next=person->next;
				person->next=node;
			}
			else
			{
				for(i=2;i<post+2;i++)
				{
					pre=cur;
					cur=cur->next;
				}
				node->next=pre->next;
				pre->next=node;
				
			}
		}
	}
	printf("\n");
	return(person);
}

stud *Reverse(stud *person)  /*对单链表进行逆序操作的函数*/
{
	stud *cur,*tmp;  //cur将代表逆序后单链表的第一个节点
		  	 //tmp代表原单链表中cur之后紧邻的节点,起交换作用

	if(person!=NULL)
	{
		cur=person->next;
		person->next=NULL;  /*将原单链表置空*/
		
		while(cur!=NULL)  /*如果cur不为NULL*/
		{
			tmp=cur->next;  /*把当前节点的下一个节点赋给tmp */
			cur->next=person->next;  //若当前节点为原链表中的第一个节点,则使其next指向NULL
						 //否则使其next指向原链表中当前节点的上一个节点,也就是正在逆序中的第一个节点
			person->next=cur;  /*使头指针指向当前节点*/
			cur=tmp;  /*把原cur的下一个节点赋给cur*/
		}
		
	}
	return(person);
}

void GetMid(stud *person)  //获取中间节点的数据
{
	stud *onestep,*twostep;  //采用步进的策略,一个每次步进1,另一个每次步进2,这样当步进为2的指针指向的节点的next为空时,另一个指针刚好指向中间节点或者中间的第一个节点

	if(N%2)  //判断以决定采用的步进策略
	{
		onestep=twostep=person->next;
		while(twostep->next!=NULL)
		{
			twostep=twostep->next->next;
			onestep=onestep->next;
		}
		printf("\n处于中间位置的人只有一个,\n\t其名称为:%s,其年龄为:%d。\n\n",onestep->name,onestep->age);
	}
	else
	{
		onestep=twostep=person;
		while(twostep->next!=NULL)
		{
			twostep=twostep->next->next;
			onestep=onestep->next;
		}
		printf("\n处于中间位置的人有两个,\n\t第一个名称为:%s,其年龄为:%d;\n\t第二个名称为:%s,其年龄为:%d。\n\n",onestep->name,onestep->age,onestep->next->name,onestep->next->age);
	}
}

void Print(stud *person)
{
	int post=1;
	stud *cur;
	cur=person->next;
	printf("当前的节点信息如下所示:\n");
	while(cur!=NULL)
	{
		printf("第%d个人的姓名是:%s,年龄为:%d;\n",post,cur->name,cur->age);
		cur=cur->next;
		post++;
	}
	N=--post;
	printf("当前单链表的长度是:%d。\n\n",N);
}

int main()
{
	int number,post,i;
	stud *head;
	head=Create(N);
	Print(head);

	for(i=0;i<times;i++)
	{
		GetMid(head);	

		printf("请输入要删除的节点的位置:\n");
		scanf("%d",&number);
		Delete(head,number);
		Print(head);

		printf("请输入要插入节点的位置(此位置是指预期插入成功后新节点在单链表中的位置):\n");
		scanf("%d",&post);
		Insert(head,post);
		Print(head);
	
		printf("以下展示了两次单链表的逆序!!!\n\n");
		Print(Reverse(head));
		Print(Reverse(head));
	
		printf("\n注意:剩余输入轮数为:%d  !!!!!\n\n",(times-(i+1)));
	}

	return 0;
}
 

 

 

调试环境:Ubuntu Desktop 8.04.4    VI 7.1.138    GCC 4.2.4
QQ:81064483
E-mail:AllenNewOK@126.com

复习之用,不足之处,敬请指正。< ^_^ >

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页