c语言 数据结构 链表,C语言数据结构链表实现代码

4-810-jpg_6-1080-0-0-1080.jpg

前言

最近回顾一下数据结构的相关知识

什么是链表

82610e6d295245ecd1f038118786ffea.gif

简而言之,链表由多个节点离散分配,并通过指针相互连接,并且每个节点只有一个先前节点和后续节点. 第一个节点没有前任节点,这是一个存储结构,其中节点没有后继节点.

链表的结构

cce2a2f1f26b48c62e858cfe2d50e57f.png

afa57022e29d439c9e8b5cbc8f5222ef.png

头节点: 链表中第一个有效节点之前的节点. 头节点不存储有效数据,即数据字段为空. 添加头节点的主要目的是简化链表的操作.

第一个节点: 链表中的第一个有效节点. 该节点包含数据字段和指针字段.

尾节点: 尾节点的指针字段为空.

824512ad45321a288c0a7b766ea77309.gif

头指针: 指向头节点的指针变量,它存储头节点的地址(请注意,这里的指针变量存储地址,即头指针存储

头节点的地址,通常通过头指针操作链表.

具体实现

5ad29fb05bd3804617a812945eaab748.png

#include

#include

#include

//定义链表节点

typedef struct Node

{

int data; //数据域

struct Node * pNext; //指针域

}NODE, * PNODE; //NODE等价于struct Node, PNODE等价于struct Node *

//函数声明

PNODE createLinkList(void); //创建链表的函数

void traverseLinkList(PNODE pHead); //遍历链表的函数

bool isEmpty(PNODE pHead); //判断链表是否为空的函数

int getLength(PNODE pHead); //获取链表长度的函数

bool insertElement(PNODE pHead, int pos, int val); //向链表中插入元素的函数,三个参数依次为链表头结点、要插入元素的位置和要插入元素的值

bool deleteElement(PNODE pHead, int pos, int * pVal); //从链表中删除元素的函数,三个参数依次为链表头结点、要删除的元素的位置和删除的元素的值

void sort(PNODE pHead); //对链表中的元素进行排序的函数(基于冒泡排序)

int main(void)

{

int val; //用于保存删除的元素

PNODE pHead = NULL; //PNODE等价于struct Node *

pHead = createLinkList(); //创建一个非循环单链表,并将该链表的头结点地址赋给pHead

traverseLinkList(pHead); //调用遍历链表的函数

if(isEmpty(pHead))

printf("链表为空!\n");

else

printf("链表不为空!\n");

printf("链表的长度为:%d\n", getLength(pHead));

//调用冒泡排序函数

sort(pHead);

//重新遍历

traverseLinkList(pHead);

//向链表中指定位置处插入一个元素

if(insertElement(pHead, 4, 30))

printf("插入成功!插入的元素为:%d\n", 30);

else

printf("插入失败!\n");

//重新遍历链表

traverseLinkList(pHead);

//删除元素测试

if(deleteElement(pHead, 3, &val))

printf("元素删除成功!删除的元素是:%d\n", val);

else

printf("元素删除失败!\n");

traverseLinkList(pHead);

system("pause");

return 0;

}

PNODE createLinkList(void)

{

int length; //有效结点的长度

int i;

int value; //用来存放用户输入的结点的值

//创建了一个不存放有效数据的头结点

PNODE pHead = (PNODE)malloc(sizeof(NODE));

if(NULL == pHead)

{

printf("内存分配失败,程序退出!\n");

exit(-1);

}

PNODE pTail = pHead; //pTail始终指向尾结点

pTail->pNext = NULL; //清空指针域

printf("请输入您想要创建链表结点的个数:len = ");

scanf("%d", &length);

for(i=0;i

{

printf("请输入第%d个结点的值:", i+1);

scanf("%d", &value);

PNODE pNew = (PNODE)malloc(sizeof(NODE));

if(NULL == pHead)

{

printf("内存分配失败,程序退出!\n");

exit(-1);

}

pNew->data = value; //向新结点中放入值

pTail->pNext = pNew; //将尾结点指向新结点

pNew->pNext = NULL; //将新结点的指针域清空

pTail = pNew; //将新结点赋给pTail,使pTail始终指向为尾结点

}

return pHead;

}

void traverseLinkList(PNODE pHead)

{

PNODE p = pHead->pNext;

while(NULL != p)

{

printf("%d ", p->data);

p = p->pNext;

}

printf("\n");

return;

}

bool isEmpty(PNODE pHead)

{

if(NULL == pHead->pNext)

return true;

else

return false;

}

int getLength(PNODE pHead)

{

PNODE p = pHead->pNext; //指向首节点

int len = 0; //记录链表长度的变量

while(NULL != p)

{

len++;

p = p->pNext; //p指向下一结点

}

return len;

}

void sort(PNODE pHead)

{

int len = getLength(pHead); //获取链表长度

int i, j, t; //用于交换元素值的中间变量

PNODE p, q; //用于比较的两个中间指针变量

for(i=0,p=pHead->pNext ; ipNext)

{

for(j=i+1,q=p->pNext;jpNext)

{

if(p->data > q->data)

{

t = p->data;

p->data = q->data;

q->data = t;

}

}

}

return;

}

bool insertElement(PNODE pHead, int pos, int val)

{

int i = 0;

PNODE p = pHead;

//判断p是否为空并且使p最终指向pos位置的结点

while(NULL!=p && i

{

p = p->pNext;

i++;

}

if(NULL==p || i>pos-1)

return false;

//创建一个新结点

PNODE pNew = (PNODE)malloc(sizeof(NODE));

if(NULL == pNew)

{

printf("内存分配失败,程序退出!\n");

exit(-1);

}

pNew->data = val;

//定义一个临时结点,指向当前p的下一结点

PNODE q = p->pNext;

//将p指向新结点

p->pNext = pNew;

//将q指向之前p指向的结点

pNew->pNext = q;

return true;

}

bool deleteElement(PNODE pHead, int pos, int * pVal)

{

int i = 0;

PNODE p = pHead;

//判断p是否为空并且使p最终指向pos结点

while(NULL!=p->pNext && i

{

p = p->pNext;

i++;

}

if(NULL==p->pNext || i>pos-1)

return false;

//保存要删除的结点

* pVal = p->pNext->data;

//删除p后面的结点

PNODE q = p->pNext;

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

free(q);

q = NULL;

return true;

}

结论

上面的实现主要是单链表,还有其他几种常见的链表,例如双链表,循环链表和非循环链表. 双向链表的特殊性在于每个基本节点都有两个指针字段. 循环链表的特征主要表现在循环链表中c 链表,其他所有节点都可以通过任意一个节点找到.

本文来自电脑杂谈,转载请注明本文网址:

http://www.pc-fly.com/a/jisuanjixue/article-168478-1.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值