单链表(有无头结点创建链表)

本文详细介绍了单链表的基本操作,包括有头节点和无头节点的初始化、头插法与尾插法建立单链表、节点的删除以及单链表的逆置。此外,还探讨了不带头节点的单链表插入和删除的实现。这些内容对于理解和操作链表数据结构至关重要。

单链表

  • 特点

1.单链表的初始化

LinkList Initlist()//单链表的初始化函数
{
	Linklist head;
	head=(Node*)malloc(sizeof(Node));
	head->next=NULL;
	return head;
}

2.单链表的建立

在头部插入新节点建立单链表

(1)有头节点

void CreatByHead(LinkList head)//头插法创建单链表
{
	Node*s;
	char name[20];
	int number;
    head->next=NULL;
	printf("请输入学生的姓名和学号:\n");
	while(1)
	{
		scanf("%s",name);
		scanf("%d",number);
		if(number==0)
		break;
		s=(Node*)malloc(sizeof(Node));
		strcpy(s->name,name);
		s->number=number;
		s->next=head->next;
		head->next=s
    }
}

本质上就是在头结点之后插入新结点
(2)无头节点

LinkList creatbyhead1(LinkList head)//头插法(无结点)
{

    int number;
    char name[20];
    LinkList s;
    while(1)
    {
        scanf("%s",name);
        scanf("%d",&number);
        if(number==0)
        break;
        s=(Node*)malloc(sizeof(Node));
        strcpy(s->name,name);
        s->number=number;
        s->next=head;
    	head=s;
        
    }
    return head;
    
}

本质上是在head(第一个结点而非头结点)之前插入结点

- 在单链表的尾部插入新结点

(1)有头点

LinkList creatnodebyrear(LinkList head)//尾插法
{
    int number;
    char name[20];
    LinkList r,s;
    r=head;
    while(1)
    {
        printf("请输入信息,名字和序号:\n");
        scanf("%s",name);
        scanf("%d",&number);
        if(number==0)
        break;
        s=(Node*)malloc(sizeof(Node));
        s->number=number;
        strcpy(s->name,name);
        r->next=s;
        r=s;
        
    }
    r->next=NULL;
}

(2)无头结点

LinkList creatlist2()//尾插法(无头结点)
{
    LinkList head=NULL;
    int number;
    char name[20];
    LinkList r,s;
    printf("请输入序号和姓名");
    while(1)
    {
        scanf("%d",&number);
        scanf("%s",name);
        if(number==0)
        break;
        s=(Node*)malloc(sizeof(Node));
        strcpy(s->name,name);
        s->number=number;
        s->next=NULL;
        if(head==NULL)
        {
            head=s;
           
        }
        else
        {
            r->next=s;
        
        }
         r=s;
        
        
    }
    return head;


}

四种建立单链表的完整代码

#include<stdio.h>
#include<stdlib.h>
typedef struct node
{
	int data;
	struct node *next;
	
}Node,*LinkList;

void CreatListByRear(LinkList head)//有头节点的尾插法 
{
	Node *r,*s;
	r=head;
	int n;
	printf("输入数据的个数:\n");
	scanf("%d",&n);
	printf("要输入的数据:\n");
	while(n--)
	{
		s=(Node*)malloc(sizeof(Node));
		scanf("%d",&s->data);
		r->next=s;
		r=s;
		
	}
	r->next=NULL;
}
LinkList CreatListByRear1(LinkList head)//没有头节点的尾插法 
{
	Node *r,*s;
	head=NULL;
	int n;
	printf("输入数据的个数:\n");
	scanf("%d",&n);
	printf("要输入的数据:\n");
	while(n--)
	{
		s=(Node*)malloc(sizeof(Node));
		scanf("%d",&s->data);
		s->next=NULL;
		if(head==NULL)
		{
			head=s;
			r=head;
		}
		else
		{
			r->next=s;
			r=s;
		}
		
	}
	return head;
 } 
CreatListByHead(LinkList head)//有头节点的头插法 
{
	Node *r,*s;
	int n; 
	head->next=NULL; 
	printf("输入数据的个数:\n");
	scanf("%d",&n);
	printf("要输入的数据:\n");
	while(n--)
	{
		s=(Node*)malloc(sizeof(Node));
		scanf("%d",&s->data);
		s->next=head->next;
		head->next=s;
	}
}
LinkList CreatListByHead1(LinkList head)//不带头节点的头插法 
{
	Node *r,*s;
	head=NULL;
	int n;
	printf("输入数据的个数:\n");
	scanf("%d",&n);
	printf("要输入的数据:\n");
	while(n--)
	{
		s=(Node*)malloc(sizeof(Node));
		scanf("%d",&s->data);
		s->next=head;//与带头节点的不同就在于head->next改为head即可 
		head=s;
	}
	return head;
}
InputList(LinkList head)//输出
{
	Node *p;
	p=head;//无头结点 
	//p=head->next;//有头节点 
	printf("存入数据为:\n");
	while(p)
	{
		printf("%d ",p->data);
		p=p->next;
	}
	
}	

int main()
{
	LinkList L1;
    L1=(Node*)malloc(sizeof(Node));
    //CreatListByRear(L1);尾插法有头节点 
	//L1=CreatListByRear1(L1); 尾插法无头节点 
	L1=CreatListByHead1(L1);// 头插法有头节点 
	InputList(L1);
}

3.单链表的删除

void deletenode(LinkList head,int pos)//删除结点(有头节点)
{
    int j=0;
    LinkList p,q;
    p=head;
    if(j<pos-1&&p)
    {
        p=p->next;
        j++;
    }
    if(p==NULL||p->next==NULL)
    printf("Error!");
    else
    {
        q=p->next;
        p->next=q->next;
        free(q);
    }
    
    
}

4.不带头结点的单链表

  • 不带头结点单链表的插入

    • 插入链表的首位置

      • 新节点的指针s指向首结点head 再让s成为新head
    • 其他位置与带头结点的一样

      LinkList Delete(LinkList head,int i)
      {
          int j=1;
          Node *p,*q;
          if(i==1)
          {
              q=head;
              head=head->next;
              free(q);
          }
          else
          {
              while(j<i-1&&p)
              {
                  p=p->next;
                  j++;
              }
              if(p==NULL||p->next==NULL)
              if(p)
              {
                  q=p->next;
                  p->next=q->next;
                  free(q);
              }
          }
          return head;
      }
      

- 不带头结点单链表的删除

  • 删除链表的首结点

    • 把让q指向head 再让head指向第二个结点成为新节点 free((q)) 这种情况需要返回新头指针
  • 其他位置与带头结点相同

    LinkList Insert(LinkList head,int i)
    {
        Node *s;
        Node *p;
        s=(Node*)malloc(sizeof(Node));
        scanf("%s",s->name);
        scanf("%d",s->number);
        int j=1;
        Node *p;
        if(i==1)
        {
            s->next=head;
            head=s;
        }
        else 
        {
            while(j<i-1&&p)
            {
                p=p->next;
                j++;
            }
            if(p)
            {
                s->next=p->next;
                p->next=s;
                
            }
        }
        return head;
    }
    

5.单链表的应用

  • 5.1单链表的逆置
struct node2 *reverselink(struct node2 *head)
{
	Node *pfirst,*pmid,*plast;
	pfirst=head;
	pmid=head->next;
	plast=head->next->next;
	if(head==NULL)
	return NULL;
	pmid->next=pfirst;
	pfirst->next=NULL;
	pfirst=pmid;
	pmid=plast;
	plast=plast->next;
	while(plast)
	{
		pmid->next = pfirst;
		pfirst=pmid;
		pmid=plast;
		plast=plast->next ;
		
	}
	pmid->next =pfirst;
	return pmid;
} 

6.数组模拟链表

//两个数组模拟链表
#include<stdio.h>
int main()
{
	int a[101],s[101];
	int n,t;
	int x,i,j,len;
	printf("存入数据的个数:\n");
	scanf("%d",&n);
	len=n+1;
	printf("存入的数据:");
	for(i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	for(i=1;i<n;i++)
	{
		s[i]=i+1;
	}
	s[n]=0;
	printf("要加入的数据:");
	scanf("%d",&x);
	a[len]=x;
	t=1;
	while(t!=0)
	{
		if(a[s[t]]>x)
		{
			s[len]=s[t];
			s[t]=len;
			break;
		}
		t=s[t];//实现递推 
	}
	t=1;//让t重新归1 
	while(t!=0)
	{
		printf("%d ",a[t]);
		t=s[t];//递推 
	}
}
	
	
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值