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

前言

最近在复习数据结构的相关知识,感觉在初学的时候还是有很多东西没有掌握,不过现在终于算是搞得比较有头绪了,所以就在写出来和大家一起分享!

什么是链表

简单的说,链表就是由多个结点离散分配,彼此通过指针相连,每个结点只有一个前驱结点和后继结点。首节点无前驱结点,为结点无后继结点的一种存储结构。

链表的结构

cce2a2f1f26b48c62e858cfe2d50e57f.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;

}

结尾语

上面实现的主要是单链表,另外还有双链表、循环链表、非循环链表等其他几种常见链表。双链表的特殊性表现在每个基本结点有两个指针域;循环链表的特性主要表现在,在循环链表中,通过任何一个结点可以找到其他所有结点。

谢谢大家的阅读,希望能帮助到大家,谢谢大家对本站的支持!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值