链表结构的线性表(C语言)

#include <stdio.h>
#include <stdlib.h>
//数据 
typedef struct
{
  int num;
}ElemType;
//定义链表结构体 
typedef struct Lnode
{
    ElemType data;
    struct Lnode *next;
}Lnode,*LinkList;

//初始化单向结构体 
void InitList(Lnode**p)
{
	*p=(Lnode*)malloc(sizeof(Lnode));
	(*p)->next=NULL;
	printf("空的单向链式线性表已经建成\n");
}
//判断单向链式线性表是否为空 
void ListEmpty(LinkList p)
{
	if(p->next==NULL)
	{
		printf("此表为空\n"); 
	}
	else
	{
		printf("此表不为空\n"); 
	}
}
//销毁某一个单向线性表 
void DestroyList(Lnode**L)
{   
    Lnode *s=*L;
    Lnode *p;
    while(s)
    {
    	p=s; 
    	s=s->next;
    	free(p);
    }
	*L=NULL;	
	printf("该线性表已经被销毁\n");
}
//清除某一个单向线性表 
void ClearList(LinkList L)
{
	Lnode *q,*p;
	p=L->next;
	while(p)
	{
		q=p->next;
		free(q);
		p=q;
	}
	L->next=NULL;
	printf("此表已经清空"); 
}
//求单向线性表的长度 
int ListLength(LinkList L)
{
	Lnode *p;
	p=L->next;
	int i=0;
	while(p)
	{
	  	i++;
		p=p->next;   	
	}
	printf("获取链表长度成功\n");
	return i;
}
//获取某个元素(单向) 
int Getelem(LinkList L,int i)
{
	Lnode *p;
	p=L->next;
	int j=1,elem;
	while(p&&j<i)
	{
		p=p->next;
		j++;
	}
	if(!p||j>i)
	{
		printf("输入的获取位置i不对");
	}
	else 
	{
		elem=p->data.num;
		return elem;
	}
 }

//获取某个元素的地址(单向线性表) 
Lnode *LocateElem_L(LinkList L,int n)
{
	Lnode *p;
	p=L->next;
	while(p&&(p->data.num!=n))
	{
		p=p->next;
	}
	return p;
}

//插入操作 
void ListInsert(LinkList L,int i,int e)
{
	Lnode *p;
	p=L;int j=0;
	while(p&&j<i-1)
	{
		p=p->next;
		j++;
	}
	if(!p||j>i-1)
	{
		printf("插入的位置错误\n");
    }
	Lnode *s=(Lnode*)malloc(sizeof(Lnode));
	s->next=p->next;p->next=s;
	s->data.num=e;
	printf("插入成功\n");
}

//删除操作
int DeleteList(LinkList L,int i)
{
	Lnode *p,*s;
	p=L;int j=0,num;
	while(p&&j<i-1)
	{
		p=p->next;
	}
	if(!p&&j>i-1)
	{
		printf("删除的位置错误");
	}
	s=p->next;
	p->next=s->next;
	num=s->data.num;
	free(s);
	printf("对应位置的节点已经删除\n");
	return num; 
}
//头插法
void CreateList_H(Lnode **L,int i)
{
   	*L=(Lnode*)malloc(sizeof(Lnode));
   	(*L)->next=NULL;
   	printf("请输入%d个整形值",i);
   	for(int j=0;j<i;j++)
   	{
   		Lnode *p;
   		p=(Lnode*)malloc(sizeof(Lnode));
   		scanf("%d",&(p->data.num));
   		p->next=(*L)->next;
   		(*L)->next=p;
	}
	printf("头插法建成的链式线性表已经完成"); 
}
//尾插法 
void CreateList_R(Lnode **L,int i)
{
	*L=(Lnode*)malloc(sizeof(Lnode));
   	(*L)->next=NULL;
   	Lnode *r;
   	r=(*L);
    printf("请输入%d个整形值",i);
   	for(int j=0;j<i;j++)
   	{
   	    Lnode *p;
   	    p=(Lnode*)malloc(sizeof(Lnode));
		p->next=NULL;
		
		scanf("%d",&(p->data.num));
		r->next=p;
		r=p;	
	}
	printf("尾插法链式表已经建成"); 
}
//带尾指针的循环链表合并
LinkList connect(LinkList Ta,LinkList Tb)
{
    Lnode *p;
	p=Ta->next;
	Ta->next=Tb->next->next;
	free(Tb->next);
	Tb->next=p;
	return Tb;
} 
int main()
{  
   
   
}

以上函数已进行过亲测可用。最近学习了链式线性表,链式线性表在代码中看就是把一个一个的结构体串在一起构成线性表。

定义链表结构体

//定义链表结构体 
typedef struct Lnode
{
    ElemType data;
    struct Lnode *next;
}Lnode,*LinkList;

结构体中定义了一个指针是为了指向下一个节点。

初始化结构体

//初始化单向结构体 
void InitList(Lnode**p)
{
	*p=(Lnode*)malloc(sizeof(Lnode));
	(*p)->next=NULL;
	printf("空的单向链式线性表已经建成\n");
}

这里用了二级指针主是为了操作指针变量,我们把一个一级指针的地址传给二级指针,那我们*(二级指针就行操作一级指针)这是指针的形参传递的方法。然后我们将头结点的next置空也就是没有数据存入,也就是一个空表。

判断链式线性表

//判断单向链式线性表是否为空 
void ListEmpty(LinkList p)
{
	if(p->next==NULL)
	{
		printf("此表为空\n"); 
	}
	else
	{
		printf("此表不为空\n"); 
	}
}

也就是头结点的指针域是否为空。

销毁链式线性表

//销毁某一个单向线性表 
void DestroyList(Lnode**L)
{   
    Lnode *s=*L;
    Lnode *p;
    while(s)
    {
    	p=s; 
    	s=s->next;
    	free(p);
    }
	*L=NULL;	
	printf("该线性表已经被销毁\n");
}

摧毁链式线性表也就是把没一个节点都给他释放了。这里用到了p=s和s=s->next 算法就可以把来链式线性表全部遍历一遍记得循环条件是否空。因为最后一个节点的指针域为空。

清除链式线性表

void ClearList(LinkList L)
{
	Lnode *q,*p;
	p=L;
	while(p)
	{
		q=p->next;
		p=q;
		free(q);
	}
	L->next=NULL;
	printf("此表已经清空"); 
}

清除链式线性表与销毁线性表最大的区别就是,头结点是没有释放的。上面的总代码有点问题,把这个替换上去,这个也是遍历习惯表,除了头结点其他的节点都被释放。

求线性表的长度

//求单向线性表的长度 
int ListLength(LinkList L)
{
	Lnode *p;
	p=L->next;
	int i=0;
	while(p)
	{
	  	i++;
		p=p->next;   	
	}
	printf("获取链表长度成功\n");
	return i;
}

这里i是一个计数器只要p不为空就要一直加,然后返回i的值就知道线性表的长度。

获取某个位置的元素值

//获取某个元素(单向) 
int Getelem(LinkList L,int i)
{
	Lnode *p;
	p=L->next;
	int j=1,elem;
	while(p&&j<i)
	{
		p=p->next;
		j++;
	}
	if(!p||j>i)
	{
		printf("输入的获取位置i不对");
	}
	else 
	{
		elem=p->data.num;
		return elem;
	}
 }

主要还是通过循环来实现,先找到i的位置然后,然后返回这时候的数据域。

插入操作

//插入操作 
void ListInsert(LinkList L,int i,int e)
{
	Lnode *p;
	p=L;int j=0;
	while(p&&j<i-1)
	{
		p=p->next;
		j++;
	}
	if(!p||j>i-1)
	{
		printf("插入的位置错误\n");
    }
	Lnode *s=(Lnode*)malloc(sizeof(Lnode));
	s->next=p->next;p->next=s;
	s->data.num=e;
	printf("插入成功\n");
}

找到插入的前一个位置p后,我们申请一个结点,然后让s->next=p->next,也就是将s的指针域指向p的下一个,再将p的指针域指向s,则插入完成。

删除操作

int DeleteList(LinkList L,int i)
{
	Lnode *p,*s;
	p=L;int j=0,num;
	while(p&&j<i-1)
	{
		p=p->next;
	}
	if(!p&&j>i-1)
	{
		printf("删除的位置错误");
	}
	s=p->next;
	p->next=s->next;
	num=s->data.num;
	free(s);
	printf("对应位置的节点已经删除\n");
	return num; 
}

删除操作,与插入操作类似,先找到前面一个节点进而找到要删的位置,用另一个指针域*s记住地址,然后在释放s,p的指针域,为s的指针域。也就是跨过了s这个节点。

头插法

//头插法
void CreateList_H(Lnode **L,int i)
{
   	*L=(Lnode*)malloc(sizeof(Lnode));
   	(*L)->next=NULL;
   	printf("请输入%d个整形值",i);
   	for(int j=0;j<i;j++)
   	{
   		Lnode *p;
   		p=(Lnode*)malloc(sizeof(Lnode));
   		scanf("%d",&(p->data.num));
   		p->next=(*L)->next;
   		(*L)->next=p;
	}
	printf("头插法建成的链式线性表已经完成"); 
}

先创建一个空表,然后开始申请要插入的节点,头插法也就是在头结点后面开始插入,让申请的指针域等于头结点的指针域,再将头结点的指针域等于p,即可。

尾插法

void CreateList_R(Lnode **L,int i)
{
	*L=(Lnode*)malloc(sizeof(Lnode));
   	(*L)->next=NULL;
   	Lnode *r;
   	r=(*L);
    printf("请输入%d个整形值",i);
   	for(int j=0;j<i;j++)
   	{
   	    Lnode *p;
   	    p=(Lnode*)malloc(sizeof(Lnode));
		p->next=NULL;
		
		scanf("%d",&(p->data.num));
		r->next=p;
		r=p;	
	}
	printf("尾插法链式表已经建成"); 
}

尾插法就是在最后插入,也就是申请到的节点指针域为空,要用一个指针标记最后一个元素,然后将这个指针指向申请到的新节点。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值