数据结构之单链表


定义:链表就是通过一组任意的存储单元(可任意连续,可以不连续)来存储线性表中的数据元素

单链表的结构

每个数据元素AI:
数据域:用来存储结点地数据值
指针域: 用来存储数据元素的直接后继的地址(或位置)

单链表的存储

在这里插入图片描述
单链表:A B C D E F G H
元素间存储物理关系不紧邻,逻辑关系紧邻
在这里插入图片描述
头结点的数据域可以存储标题、表长等信息,也可以不存储任何信息,其指针域存储第一个结点的首地址。

单链表的建立

头插法

思想:首先申请一个头结点,并且将头结点指针域置空(NULL);然后每读入一个数据元素则申请一个结点,并插在链表的头结点之后。
在这里插入图片描述
由于是在头部插入,所以数据的读入顺序和线性表中的逻辑顺序是相反的

struct Node *creat()
{
	int x;
	struct Node *h,*p,*q;
	h=(struct Node *)malloc(sizeof(struct Node));
	h->next=NULL;
	scanf("%d",&x);
	while(x!=-1)
	{

		q=(struct Node *)malloc(sizeof(struct Node));
		q->data=x;
		q->next=h->next;
		h->next=q;
		scanf("%d",&x);
	}
	return h;
}

在这里插入图片描述

尾插法

思想:在单链表的尾部插入节点建立单链表,简称“尾插法”。由于每次是将新结点插入到链表的尾部,所以增加一个指针r来始终指向链表中的尾结点,以便能够将新结点插入到链表的尾部。
在这里插入图片描述
由于是在尾部插入的,所以数据的读入顺序和线性表的逻辑顺序是一致的

struct Node *creat()
{
	int x;
	struct Node *h,*p,*q;
	h=(struct Node *)malloc(sizeof(struct Node));
	h->next=NULL;
	p=h;
	q=(struct Node *)malloc(sizeof(struct Node));
	scanf("%d",&x);
	q->data=x;
	while(x!=-1)
	{
		p->next=q;
		p=p->next;
		scanf("%d",&x);
		q=(struct Node *)malloc(sizeof(struct Node));
		q->data=x;
	}
	p->next=NULL;
	return h;
}

在这里插入图片描述

单链表的基本运算

单链表地插入

和创建类似。

void ListInsert_L(LinkList &L,int i,ElemType e){
    //在带头结点的单链线性表L中第i个位置之前插入元素e
    LinkList p=L;int j=0;
    while(p&&j<i-1){
        p=p->next;++j;
    }//寻找第i-1个节点
    if(!p||j>i-1) return ERROR;
    LinkList s;
    s=(LinkList)malloc(sizeof(LNode));
    s->data=e;s->next=p->next;
    p->next=s;
    return OK;
}//ListInsert_L

单链表删除

思想:先找到这个数据所在结点,是头结点修改头结点,删除头结点,free该结点;不是头节点,直接删除该结点(使此结点的前驱直接等于此结点的后继,此结点的后继结点的前驱等于此结点的前驱)
在这里插入图片描述

void  ListDelete_L (LinkList &L,int i,ElemType &e){
    //在带头结点的单链表L中,删除第i个元素,并由e返回其值
    LinkList p;
    LinkList q;
    p=L; int j=0;
    while(p->next&&j<i-1){//寻找第i个节点,并令p指向其前驱
        p=p->next;++j;
    }
    if(!(p->next)||j>i-1) return ERROR; //删除位置不合理
    q=p->next;p->next=q->next;//删除并释放节点 
    e=q->data; free(q);
    return OK; 
     
}//ListDelete_L

存储空间的分配和释放

malloc函数

malloc原型: void* malloc(unsigned int size);
malloc(动态内存分配):申请一块连续的指定大小的内存块区域以void*类型返回分配的内存区域地址,当无法知道内存的具体位置时,想要绑定真正的内存空间,就需要用到动态的分配内存,且分配的大小就是程序要求的大小。
使用方法:
p=(LinkList)malloc(sizeof(LNode))

malloc和new的区别

1、new返回指定类型的指针,并且可以自动计算所需要的大小。
malloc必须要由我们计算字节数,并且在返回后强行转换为实际类型的指针。
2、malloc只管分配内存,并不能对所得的内存进行初始化,所以得到的一片新内存,其值将是随机的。

calloc函数

calloc原型:void* calloc(unsigned int num,unsigned int size);
**calloc(动态内存分配并做初始化):**在内存的动态存储区中分配num个长度为size的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL。
num:对象个数 size:对象占据的内存字节数 calloc会自动将内存初始化为0

与malloc的区别

calloc在动态分配内存后,自动初始化该内存为0,而malloc不做初始化,分配到空间中的数据是随机数据。

relloc

free函数

free函数原型:void free(void *ptr)
free:释放之前调用calloc、malloc所分配的内存空间
如果一个指针删除之后,不进行释放,内存块无法再被程序使用,如果耗尽了内存池,会导致以后的临时申请语句申请失败

双向链表

在这里插入图片描述

循环链表在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值