数据结构之链表

学习目的

看懂能敲出链表,看懂伪算法,有机会自学数据结构。

链表

顺序存储(连续存储)

  1. 顺序存储的缺点

以C语言数组插入一个元素为例,当我们需要在一个数组{1,2,3,4,5,6,7}的第1个元素后(即第2个元素)的位置插入一个’A’时。我们需要做的有,将第1个元素后的整体元素后移,形成新的数组{1,2,2,3,4,5,6,7},再将第2个元素位置的元素替换为我们所需要的元素’A’,最终形成我们的预期,一个简单的插入操作要进行那么多的步骤。

其一:所需要移动的元素很多,浪费算力。

其二:必须为数组开足够多的空间,否则有溢出风险。

链表-链式存储

  1. 定义

n个节点离散分配,彼此通过指针相连,每个节点只有一个前驱节点,一个后续节点,首节点没有前驱节点,尾节点没有后续节点。

专业术语:

首节点:第一个有效的节点。

尾节点:最后一个有效的节点。

头节点:首节点之前的节点。

头节点的数据类型和首节点数据类型相同

不存放有效数据,不存放有效节点的个数。

头节点的作用:方便对链表进行操作。

头指针:指向头节点的指针变量。

尾指针:指向尾节点的指针变量。

确定一个链表需要几个参数:

一个参数:头指针

链表节点如何开辟:

# include <stdio.h>

typrdef struct Node
{
    int data;//数据域
    struct Node * pNext;//指针域
}NODE, *PNODE;//NODE等价于struct Node, PNODE等价于struct Node *。
int main(void)
{
    
    return 0;
}

同任何的结构,类型一样,链表也需要初始化操作,初始化是创建一个单链表的前置节点并向后逐步添加节点,一般来说,我们所谓的初始化单链表一般指的是申请结点的空间,同时对一个结点辅以空值(NULL)

(一定要注意是否开辟空间失败)

  1. 分类

单链表:单链表是一种链式存取的数据结构,,链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。以“结点的序列”表示的线性表称作线性链表(单链表),单链表是链式存取的结构。

双链表:每一个节点有两个指针域。

循环链表:能通过任何一个节点找到其他全部节点。

非循环链表

  1. 伪算法

非循环单链表插入节点伪算法:

p指向一个节点,q指向一个节点,r指向一个节点

1.先把要插入位置前一个节点的指针域赋给另外一个值。

再把要插入的前一个节点的指针域指向要插入的值。

最后使插入的节点的指针域指向要插入位置的下一个节点。

            r = p->pNext;
            p->pNext = q;
            q->pNext = r;

2.

            q->pNext = p->pNext;
            p->pNext = q;

删除非循环单链表删除伪算法:

删除p节点后面的节点,即使p节点直接指向下下个节点

先定义一个指向p后面节点的指针r//为了释放内存,同时使链表不会断掉
r = p->pNext;
p->pNext = r->pNext;
free(r);
  1. 算法

遍历,查找,清空,销毁,求长度,排序,删除节点

链表创建:

在初始化之后,就可以着手开始创建单链表了,单链表的创建分为头插入法和尾插入法两种,两者并无本质上的不同,都是利用指针指向下一个结点元素的方式进行逐个创建,只不过使用头插入法最终得到的结果是逆序的。(下面的程序用的是尾插入法)

链表遍历:

进行遍历的思路极其简单,只需要建立一个指向链表L的结点,然后沿着链表L逐个向后搜索即可。

简单的遍历设计的函数只需要void无参即可,而当我们需要进行元素修等涉及到元素操作时,我们可以设计一个PNODE类型的函数,使其返回一个修改后的新链表。

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

PNODE creat_list(void);
traverse_list(PNODE pHead);

typedef struct Node
{
int date;//数据域
struct Node * pNext;//指针域
}NODE,*PNODE;//NODE等价于struct Node,PNODE等价于struct Node *

int main(void)
{
PNODE pHead = NULL;//等价于struct Node * pHead = NULL;

pHead = creat_list();//创建一个非循环单链表,并将该链表的头指针传给遍历数组完成遍历。
traverse_list(pHead);//遍历链表输出

return 0;
}

PNODE creat_list(void)
{
int len;//用来存放有效节点的个数
int i;
int val;//用来临时存放用户输入的节点的值
PNODE pHead = (PNODE)malloc(sizeof(NODE));
if(NULL == pHead)
{
printf("分配失败,程序终止!\n");
exit(-1);
}//分配头节点的内存
PNODE pTai = pHead;//创建一个始终指向尾节点的节点
pTail-> = NULL;//把头指针的指针域赋值为空使得当用户输出的链表结点个数为0时,其依然可以进行输出。

printf("请输入您要生成的链表节点的个数:len = ");
scanf("%d",&len);

for(i=0;i<len;++i)
{
printf("请输入第%d个节点的值",i+1);
scanf("%d",val);

PNODE pNew = (PNODE)malloc(sizeof(NODE));
if(NULL == pHead)
{
printf("分配失败,程序终止!\n");
exit(-1);
}//分配新节点的内存
pNew->data = val;//将所需要的值赋值给新节点
pTail->pNext = pNew;//将新节点变为尾节点
pNew->pNext = NULL;//将新节点的指针域变成空,表示其为尾指针
pTail = pNew;//再生成一个指向尾节点的节点。
}
}
void traverse_list(PNODE pHead)
{
PNODE p = pHead->pNext;

while(NULL != p)
{
printf("%d",p->data);
p = p->pNext;
}
printf("\n");
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值