单链表基础

代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

typedef int datatype;

typedef struct node{
       datatype data;
       struct node *next;
}node,*Linklist; //定义链表结点

node* createlist();//1.声明创建链表的函数
void print();//2.声明链表遍历的函数
void big();//3.声明链表长度的函数
void clear();//4.声明清除链表的函数
void null();//5.声明链表为空判断函数
int find();//6.声明查找函数
void getaddr();//7.声明根据定值找地址函数
void change();//8.声明修改某个节点值的函数
void inserthead();//9.声明表头插入函数
void inserttail();//10.声明表尾插入函数
void insertmiddle();//11.声明中间插入函数
void delet();//12.声明删除节点函数

node * createlist(node *head)//创建函数定义  ----->尾插法:
{
node *p1;//新节点
node *p2;//尾节点 
p1=p2=(node*)malloc(sizeof(node));
if(p1==NULL || p2==NULL)
{printf("mallocerror!\n");}
scanf("%d",&(p1->data));
p1->next=NULL;

while(p1->data>0) //大于0的整数
{
if(head ==NULL)
{head =p1;//空表 p1为头节点
p2=head;}
else
{
p2->next=p1;
p2=p1;//保证p2为尾节点
}
p1=(node*)malloc(sizeof(node));
scanf("%d",&(p1->data));
}
free(p1);
p2->next=NULL;//尾节点的next为NULL
printf("create done!\n");
return head;
}
/*-------------------------------------------------
头插法:p->next=head;head=p; 遍历数据倒着输出
node * createlist(node *head)
{
	node*p;
  p=(node*)malloc(sizeof(node));
  scanf("%d",&(p->data));
  while(p->data>0)
  {
  	p->next=head;
  	head=p;
  	p=(node*)malloc(sizeof(node));
    scanf("%d",&(p->data));
  	
  }
	return head;
}
------------------------------------------*/

void print(node *head)//链表遍历函数的定义
{
node *tmp;//定义临时指针去遍历
tmp =head;
while(tmp!=NULL)
{
printf("%d\n",tmp->data);
tmp =tmp->next;
}
printf("print done!\n");
return ;
}
void big(node *head)//链表长度函数长度
{
	int listlong=0;
	if(head ==NULL)
	{	printf("listlong=0\n");
		return ;
	}
	while(head !=NULL)
	{
		listlong++;
		head=head->next;
	}
	printf("listlong done!andlistlong=%d\n",listlong);
	return ;
}

void clear(node **head)//传入二级指针否则无法改变指针的地址值,无法删除节点
{
	node *mv=NULL;//头节点的下个节点
	if(*head ==NULL)
		return ;//表空直接返回
	
	while((*head)->next !=NULL)
	{
		mv=(*head)->next;//保存头节点的下个节点
		free((*head));//删除头节点
		(*head)=mv;//头节点下移
	}
		if((*head) != NULL)//最后一个节点!!!容易忘掉
			{
				free(*head);
			*head =NULL;
		  }
		printf("cleanlist done!\n");  
		  return ;
}

void null(node *head)//链表是否为空判断定义
{
	if(head ==NULL)
		printf("List is NULL!\n");
		else
			printf("List is FULL!\n");
	return ;		
}

int find(node *head,int num)//查看链表第num个节点的数据
{
	int i=0;
	if(num<1 || head==NULL)
		{
			printf("find error:list is NULL or illegal input!\n");
		}
	while(head !=NULL)
	{
		i++;
		if(i==num) 
	{
		break;
	}
	head=head->next;
	
  }
	if(i<num)
		{printf("find too long try again!\n");
			return 0;
			}
	printf("find done!\n");	
		return  head->data;	
}

void getaddr(node *head,int x)//求地址
{
	if(head==NULL || x<1)
		{
			printf("getaddr error:list is null or illegal input!\n");
			return ;
		}
	while((head ->next!=NULL)	&&  (head->data !=x))//链表未到表尾且没找到x!
	{
		head=head->next;
	}
	if((head !=NULL)	&&  (head->data !=x))
		{
			printf("not found x in list and getaddr bad!\n");
			return ;
		}
	if(head->data ==x)	
		printf("getdaddr done! x=%d ,addr=%p\n",x,&(head->data));
		return ;
}
//****传入二级指针会改变头节点的地址,从而只能遍历出移动位置之后的链表值
void change(node *head,int i,datatype value1)//改变某个节点的值
{
	int n=1;
	node *nod=head;//临时节点去查找
	if(i<1 || head==NULL)
		{
			printf("change error:list is NULL or illegal input!\n ");
			return ;
		}
	while(head !=NULL)
	{
		if(n==i)
			{
			 head=nod;
		   head->data=value1;//替换值
		   printf("change value done!\n");
			 break;
			}
		nod = nod->next;//移动节点
		n++;
	}
	if(n<i)
		{
			printf("change value beyond list!\n");
			return ;
		}
		return  ;
}

void inserthead(node **head,datatype value1)//表头插入某值 表头需要动的用二级指针
{
	node *insert;
	if( head==NULL)
		{
			printf("change error:list is NULL or illegal input!\n ");
			return ;
		}
	if(!(insert =(node*)malloc(sizeof(node))))
	{
		printf("malloc error!\n");
	}
	memset(insert,0,sizeof(node));
	insert->data=value1;
	insert->next=*head;
	*head=insert;
	printf("inserthead done!\n");
	return ;
}

void inserttail(node *head,datatype value2)//表尾插入 需要中间节点去保存头节点
{
	node* tmp;//保存头节点中间节点
	node *insert;
	tmp=head;//保存头节点
	if( head==NULL)
		{
			printf("change error:list is NULL or illegal input!\n ");
			return ;
		}
	if(!(insert =(node*)malloc(sizeof(node))))
	{
		printf("malloc error!\n");
	}
	memset(insert,0,sizeof(node));
	insert->data=value2;
	insert->next=NULL;//表尾为NULL
	while((head)->next !=NULL)
	{
		(head)=(head)->next;//头节点移动直到表尾
	}
	(head)->next=insert; //插入节点到表尾
	head=tmp;//中间节点=头节点
	printf("inserttail done!\n");
	return;
}

void insertmiddle(node *head,int i,datatype value3)
{
	int n=1;
	node * tmp; //临时节点保存头节点
	node *insert;
	node *next;
	tmp=head;//保存头节点
	if(i<1 || head==NULL)
		{
			printf("change error:list is NULL or illegal input!\n ");
			return ;
		}
	
	while((head) !=NULL)
	{
		if(n==i)
			{
				if(!(insert =(node*)malloc(sizeof(node))))//找到后申请节点空间!
	     {
		     printf("malloc error!\n");
	     }
	      memset(insert,0,sizeof(node));
	    next=head->next;//保存当前节点的下一个节点!!!这二
	    insert->data=value3;//插入数据
	    (head)->next=insert;//插入节点
      insert->next=next;//查入节点连入链表
	   	//insert->next=(head)->next->next;//搞笑了。。。(head)->next->next不确定啊。。两侧都不确定
		 }
		 (head)=(head)->next;//移动节点
		 n++;
	}
	head=tmp;//还原头节点	只要不是二级指针就不会改变头节点这个其实多余!
	printf("insertmiddle done!\n");
	return ;
}

void delet(node **head,int i)//删除节点
{
	int n=1;
	node *tmp;
	node *NODE;
	NODE=*head;
	if(i<1 || *head==NULL)
		{
			printf("change error:list is NULL or illegal input!\n ");
			return ;
		}
	if(*head !=NULL)
	{
		if(n==i==1)//删除头节点!
			{
				printf("delete head node!\n");
				tmp=(*head)->next;//保存第二个节点指针
				(*head)->next=NULL;
				*head=tmp;//第二个节点指针为头指针
				return ;
			}
		while(n<i-1) //10----11
		{
			*head=(*head)->next;
			if(((*head)->next) ==NULL)
				{
					printf("delete node beyond list!\n");
					*head=NODE;//删除失败返回完整链表!
					return;
				}
			n++;	
		}
		tmp=(*head)->next;//保存删除节点指针
		(*head)->next=(*head)->next->next;
		free(tmp);
	}	
		*head=NODE;
	printf("delete node done!\n");	
	return;	
}

int main()
{
int findnumber;
int m,mm,node,node1,node2,value,insert,insert1,insert2;
Linklist head1 =NULL; //初始化链表即是使表头指针为NULL,不必再定义函数。
head1 =createlist(head1);
print(head1);
big(head1);
printf("input number what you want find! inputnumber is:");
scanf("%d",&m);
if(findnumber=find(head1,m))
printf("find ok!findnumber=%d\n",findnumber);
printf("input data what you want get address! inputdata is:");
scanf("%d",&mm);
getaddr(head1,mm);
printf("input value and node what you want change!input two:");
scanf("%d,%d",&node,&value);
change(head1,node,value);
print(head1);
printf("input value  what you want insert in head!input is:");
scanf("%d",&insert);
inserthead(&head1,insert);//头节点需要动的才传二级指针
printf("input value what you want insert in last!input is:");
scanf("%d",&insert1);
inserttail(head1,insert1);
printf("input value and node what you want insert in middle!input two is:");
scanf("%d,%d",&node1,&insert2);
insertmiddle(head1,node1,insert2);
print(head1);
printf("input node what you want delete in List!input is:");
scanf("%d",&node2);
delet(&head1,node2);
print(head1);
clear(&head1);//传入二级指针
big(head1);
null(head1);
return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值