<数据结构>带头节点的单链表实现(C语言)

带头节点的单链表实现

#include <stdio.h>
#include <stdlib.h>//包含动态分配内存空间函数 malloc()和释放空间函数free()
#include <stdio.h>

typedef struct LNode{

	int data;
	struct LNode *next;

}LNode,*LinkList;

LNode* List_Tail(LNode *L){//尾插法建立单链表


	L=(LNode*)malloc(sizeof(LNode));
	//此处为了使尾插法得时间复杂度降到O(n)级别,除头节点外额外设置了一个尾指针r (for rear)
	LNode *s;
	LNode *r=L;//初始的表尾和表头重合 同时rear==L也是队的判空条件 不过这都是后话了

    int x;
    scanf("%d",&x);

	while(x!=9527){
		s=(LNode*)malloc(sizeof(LNode));
	    s->data=x;
	    r->next=s;
		r=s;
        scanf("%d",&x);
	}

	r->next=NULL;//表尾元素后继置空

	return L;

}



LNode* List_HeadInsert(LNode *L){//头插法建立单链表
	LNode *s;

	L=(LNode*)malloc(sizeof(LNode));
	L->next=NULL;//置空初始操作 因为内存中可能有脏数据影响单链表建立
	L->data=5;

    int x;
    printf("请输入单链表元素");
    scanf("%d",&x);

	while(x!=9527){
		s=(LNode*)malloc(sizeof(LNode));
	    s->data=x;
	    s->next=L->next;
		L->next=s;
		scanf("%d",&x);
	}


	return L;
}




int length(LinkList L){//度量单链表长度
	LNode*p=L->next;//p从第一个数据节点开始
	int len=0;
	if(L==NULL)return len;
	while(p!=NULL){
		p=p->next;
		len++;

	}
	return len;

}

int Empty(LinkList L){//本应将返回值定义为_Bool类型的函数,暂将该函数返回值定为int
   if(L->next==NULL)return 1;
   else return 0;



 }

void PrintList(LinkList L){//打印整张表
	LNode *p;
	p=L->next;
    printf("该单链表元素为");
	for(int j=0;j<length(L);j++){
	  if(j==0)printf("单链表内元素分别为%d ",p->data);
	  else printf("%d ",p->data);

	  p=p->next;



}



}

LNode *GetElem(LinkList L,int i){

	if(i<1||i>length(L))return NULL;
    if(i==0)return L;//此处若i 的值为一返回L即表头节点 但在ListDelete()处失效 在失效处还需额外加上i==0的情况


	int k=1;
	LNode *p=L->next;
	while(p&&k<i){
	 	p=p->next;
		k++;
	}

	return p;

}

LNode *LocateElem(LinkList L,int e){
	if(!L)return NULL;
	LNode *p=L;
	while(p){
		if(p->data==e)break;
		p=p->next;

	}

	return p;
}

int ListInsert(LinkList L,int i,int e){//指定节点的后插操作 使用之前实现的GetElem()函数来找到第i-1个节点称之为*p节点,插入节点为*s
    if(i<1||i>length(L))return 0;//判断i的值是否合法
    LNode* p=GetElem(L,i-1);
    LNode* s=(LNode*)malloc(sizeof(LNode));
    s->data=e;
    s->next=p->next;
    p->next=s;
    return 1;


}

int forward_ListInsert(LinkList L,int i,int e){//单链表中通常采取后插法,当从表头按位查找到元素的复杂度为O(n)时对第i位的前插可以转化为对i-2位的后插
    //此处是王道书上讲的依旧后插但是*p和*s的数据互换
    if(i<1||i>length(L))return 0;//判断i的值是否合法
    LNode* p=GetElem(L,i-1);
    LNode* s=(LNode*)malloc(sizeof(LNode));
    s->data=p->data;
    s->next=p->next;//此处*s作为后插元素节点数据为 p->data
    p->next=s;
    p->data=e; //此处*p节点数据值为e

    return 1;


}


int ListDelete(LinkList L,int i){//按位删除元素值
    if(i<1||i>length(L))return 0;//判定i的值是否合法
    LNode *p;
    if(i==1)
    p=L;
    else
    p=GetElem(L,i-1);

    LNode *q=p->next;
    int e=q->data;
    p->next=p->next->next;


    free(q);
    printf("按值删除操作已完成\n\n");

    return e;

}



void DestroyList(LinkList L){//依次由头节点删除并释放整张表
     L=L->next;
     int i=1;

     while(L){

        LNode*temp=L;
        printf("删除单链表中第%d个的元素,值为%d\n",i,temp->data);

        L=L->next;
        free(temp);
        i++;
     }
     free(L);


}

int main()
{
   LNode *temp;
   temp=List_HeadInsert(temp);//规定
   //temp=List_Tail(L);
   PrintList(temp);

   printf("\n");
   printf("\n");

   printf("单链表长度为%d\n",length(temp));

   printf("\n");

   printf("该链表第三个元素为%d\n",GetElem(temp,3)->data);

   printf("\n");

   printf("该链表的按值查找元素为%d\n",LocateElem(temp,5)->data);

   printf("\n");

   if(Empty(temp))printf("这是个空的单链表");else printf("这是个非空的单链表\n");

   printf("\n");

   //ListInsert(temp,3,1216);//这里是索尔和查克的彩蛋
   forward_ListInsert(temp,3,1216);

   PrintList(temp);

   printf("\n");
   printf("\n");

   ListDelete(temp,1);

   PrintList(temp);

   printf("\n");
   printf("\n");

   DestroyList(temp);

   return 0;

}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

巴巴_羊

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

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值