数据结构-链表的操作
Posted 坏坏-5
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构-链表的操作相关的知识,希望对你有一定的参考价值。
链表综合程序
主函数
# include <stdio.h>
# include <malloc.h> //使用了malloc函数
# include <stdlib.h> //使用了exit函数
typedef struct Node
{
int data; //数据域
struct Node * pNext; //指针域
}NODE, *PNODE; //NODE等价于struct Node,PNODE等价于struct Node *
/*函数声明,可以不写形参名,但是必须声明形参类型*/
PNODE Create_list(void); //创建链表
void Traverse_list(PNODE); //遍历链表
bool Is_empty(PNODE); //判断链表是否为空
int Length_list(PNODE); //判断链表的长度
bool Insert_list(PNODE, int, int); //在链表中插入元素
bool Delete_list(PNODE, int, int *); //删除链表中的元素
void Sort_list(PNODE); //对链表中的数据排序
int main(void)
{
PNODE pHead = NULL;
int val; //用于保存被删除的元素
printf("----------------创建链表----------------\\n");
pHead = Create_list(); //创建链表
printf("\\n----------------遍历链表----------------\\n");
printf("链表中的元素为:\\n");
Traverse_list(pHead); //遍历链表
printf("------------判断链表是否为空------------\\n");
if(Is_empty(pHead)) //判断链表是否为空
printf("链表为空!\\n");
else
printf("链表非空!\\n");
printf("----------------插入元素----------------\\n");
Insert_list(pHead, 3, 25); //链表插入结点
printf("链表中的第3个位置插入元素25后,链表为:\\n");
Traverse_list(pHead);
printf("----------------元素排序----------------\\n");
Sort_list(pHead); //对链表中的元素进行排序
printf("对链表中的元素进行排序后为:\\n");
Traverse_list(pHead);
printf("--------------判断链表长度--------------\\n");
int len = Length_list(pHead); //判断链表长度
printf("链表长度为:%d\\n", len);
printf("----------------删除元素----------------\\n");
if(Delete_list(pHead, 2, &val)) //删除链表中的第2个元素
printf("删除的是第2个元素:%d\\n删除成功!\\n", val);
else
printf("删除失败!\\n");
printf("删除后链表中的元素为:\\n");
Traverse_list(pHead);
return 0;
}
创建链表函数
/*创建非循环单链表,并将该链表的首结点地址返回*/
PNODE Create_list(void)
{
int len; //用于存放有效结点的个数
int i;
int val; //用于临时存放用户输入的结点的值
/*分配不存放有效数据的头指针*/
PNODE pHead = (PNODE)malloc(sizeof(NODE));
/*
定义一个PNODE(struct Node *)类型的变量pHead,
pHead由malloc函数分配内存空间,所占大小为
NODE(struct Node)所占大小
*/
/*判断内存是否分配成功,未成功分配内存则终止程序*/
if (NULL == pHead)
{
printf("分配失败!程序终止!\\n");
exit(-1); //终止程序
}
/*分配存储最后一个尾结点的指针*/
PNODE pTail = pHead;
pTail->pNext = NULL;
/*用户输入链表的长度*/
printf("请输入您需要生成的链表结点个数:");
scanf("%d", &len);
/*用户输入每一个结点的数据*/
for (i = 0; i < len; i++)
{
printf("请输入第 %d 个结点的值:", i + 1);
scanf("%d", &val);
/*新分配一个结点,用于临时存放用户输入的数据*/
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if (NULL == pNew)
{
printf("分配失败!程序终止!\\n");
exit(-1); //终止程序
}
/*将之后每分配的结点挂在前一个结点后*/
pNew->data = val;
pTail->pNext = pNew;
pNew->pNext = NULL;
pTail = pNew;
}
return pHead; //返回第一个存放有效数据的结点地址
}
- 使用malloc函数动态分配一个头指针(pHead),指向首结点
- if语句判断头指针是否分配成功(NULL==pHead)
- 使用malloc函数动态分配一个尾指针(pTail),指向尾结点
- if语句判断尾结点是否分配成功(NULL==pHead)
- 当链表中只有一个结点时,pTal就等于pHead,且指针域为空(NULL)
- 使用for循环,对链表的长度以及元素进行赋值
- 在循环体内,再动态分配一个临时结点(pNew),用于临时存放新加入结点的数据
- 将用户输入的值赋值给pNew中的data,同时把pNew中的指针域清空(pNext=NULL)
- 再使pTail中的pNext指向pNew,即将pNew挂在首结点后
- 使pTail的值等于pNew,即pTail指向尾结点
- 最后返回pHead,即存指向首结点的指针
遍历链表函数
/*遍历链表*/
void Traverse_list(PNODE pHead)
{
PNODE p = pHead->pNext; //定义结点的指针,pHead指向的下一个结点地址
/*
判断指向下一个结点地址是否为NULL,是则表明是最后一个结点
否则输出这个结点中的数据部分,并使p指向下一个结点
*/
while(NULL != p)
{
printf("%d ", p->data);
p = p->pNext;
}
printf("\\n");
return;
}
判断链表是否为空函数
/*判断链表是否为空*/
bool Is_empty(PNODE pHead)
{
/*如果头指针指向的下一个结点为NULL,则表明链表中没有结点*/
if (NULL == pHead->pNext)
return true;
else
return false;
}
判断链表的长度函数
/*判断链表的长度*/
int Length_list(PNODE pHead)
{
/*定义临时结点指针p,p指向首结点*/
PNODE p = pHead->pNext;
int len = 0;
/*
判断p是否为空,为空则表明是最后一个结点,否则执行长度+1
同时把p指向下一个结点
*/
while(NULL != p)
{
++len;
p = p->pNext;
}
return len; //返回链表的长度
}
在链表中插入结点函数
/*向链表的第pos个结点前插入一个新的结点,值为val*/
bool Insert_list(PNODE pHead, int pos, int val)
{
int i = 0;
PNODE p = pHead;
/*
pHead指向一个链表,并且插入的位置要大于0,即只能在1之后的位置插入结点,
包括1,不能在负数位置插入结点
i用来统计链表的长度,插入的位置只能是链表长度的下一个结点,不能
是下下一个结点,即中间不能空一个结点
*/
while(NULL != p && i < pos - 1)
{
p = p->pNext;
i++;
}
/*如果插入结点的位置大于链表长度+1,或p没有指向一个链表,返回false*/
if (i > pos - 1 || NULL == p)
return false;
/*定义一个临时结点,用于存放用户输入的数据*/
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if (NULL == pNew)
{
printf("动态内存分配失败!\\n");
exit(-1);
}
/*将新分配的结点挂在链表上*/
pNew->data = val;
PNODE q = p->pNext;
p->pNext = pNew;
pNew->pNext = q;
return true;
}
- 将插入结点的数据赋值给pNew中的data
- 定义临时结点指针q,用于存放p原本指向的下一个结点
- 将p中的pNext指向新分配的存放数据的临时结点(pNew)
- 将pNew中的pNext指向q,即原本p指向的下一个结点
对链表中的数据排序函数
/*对链表中的元素进行排序*/
void Sort_list(PNODE pHead)
{
int i, j, t;
int len = Length_list(pHead); //链表长度,用于判断比较的次数
PNODE p, q; //用于指向两个不同的结点,便于进行比较
/*
p指向首结点,条件不成立,p则指向下一个结点
q指向p的下一个结点,条件不成立,q则指向下一个结点
i表示使用第i个结点,j表示与i进行比较的后续结点
*/
for (i = 0, p = pHead->pNext; i < len - 1; i++, p = p->pNext)
{
for (j = i + 1, q = p->pNext; j < len; j++, q = q->pNext)
{
/*
判断第i个结点中的数据是否大于第j个结点中的数据
是则互换数据部分,否则与第j个结点的下一个结点进行比较
*/
if (p->data > q->data)
{
t = p->data;
p->data = q->data;
q->data = t;
}
}
}
return; //表示函数调用结束
}
删除链表中的结点函数
/*删除链表中pos位置的元素*/
bool Delete_list(PNODE pHead, int pos, int * pVal)
{
int i = 0;
PNODE p = pHead;
/*
p不指向链表中的最后一个结点,
p指向删除位置前的一个结点
*/
while(NULL != p->pNext && i < pos - 1)
{
p = p->pNext;
i++;
}
/*删除的位置大于链表的长度或者p是最后一个结点,返回false*/
if (i > pos - 1 || NULL == p->pNext)
return false;
/*将删除后的结点挂在删除结点前的结点上*/
PNODE q = p->pNext; //定义临时结构体指针,存放删除结点的指针
*pVal = q->data; //把删除的数据存放在pVal中
/*删除p结点后面的结点*/
p->pNext = p->pNext->pNext; //使p->pNext跳过被删除的结点,指向下一个结点
free(q); //将q结点,即被删除的结点存储空间释放
q = NULL; //使q为空
return true;
}
完整程序
/*
1.创建链表
2.遍历链表
3.判断链表是否为空
4.输出链表长度
5.在链表中插入结点
6.对链表中个结点中的数据进行排序
7.删除链表中的结点
*/
# include <stdio.h>
# include <malloc.h> //使用了malloc函数
# include <stdlib.h> //使用了exit函数
typedef struct Node
{
int data; //数据域
struct Node * pNext; //指针域
}NODE, *PNODE; //NODE等价于struct Node,PNODE等价于struct Node *
/*函数声明,可以不写形参名,但是必须声明形参类型*/
PNODE Create_list(void); //创建链表
void Traverse_list(PNODE); //遍历链表
bool Is_empty(PNODE); //判断链表是否为空
int Length_list(PNODE); //判断链表的长度
bool Insert_list(PNODE, int, int); //在链表中插入元素
void Sort_list(PNODE); //对链表中的数据排序
bool Delete_list(PNODE, int, int *); //删除链表中的元素
int main(void)
{
PNODE pHead = NULL;
int val; //用于保存被删除的元素
printf("----------------创建链表----------------\\n");
pHead = Create_list(); //创建链表
printf("\\n----------------遍历链表----------------\\n");
printf("链表中的元素为:\\n");
Traverse_list(pHead); //遍历链表
printf("------------判断链表是否为空------------\\n");
if(Is_empty(pHead)) //判断链表是否为空
printf("链表为空!\\n");
else
printf("链表非空!\\n");
printf("----------------插入元素----------------\\n");
Insert_list(pHead, 3, 25); //链表插入结点
printf("链表中的第3个位置插入元素25后,链表为:\\n");
Traverse_list(pHead);
printf("----------------元素排序----------------\\n");
Sort_list(pHead); //对链表中的元素进行排序
printf("对链表中的元素进行排序后为:\\n");
Traverse_list(pHead);
printf("--------------判断链表长度--------------\\n");
int len = Length_list(pHead); //判断链表长度
printf("链表长度为:%d\\n", len);
printf("----------------删除元素----------------\\n");
if(Delete_list(pHead, 2, &val)) //删除链表中的第2个元素
printf("删除的是第2个元素:%d\\n删除成功!\\n", val);
else
printf("删除失败!\\n");
printf("删除后链表中的元素为:\\n");
Traverse_list(pHead);
return 0;
}
/*创建非循环单链表,并将该链表的首结点地址返回*/
PNODE Create_list(void)
{
int len; //用于存放有效结点的个数
int i;
int val; //用于临时存放用户输入的结点的值
/*分配不存放有效数据的头指针*/
PNODE pHead = (PNODE)malloc(sizeof(NODE));
/*
定义一个PNODE(struct Node *)类型的变量pHead,
pHead由malloc函数分配内存空间,所占大小为
NODE(struct Node)所占大小
*/
/*判断内存是否分配成功,未成功分配内存则终止程序*/
if (NULL == pHead)
{
printf("分配失败!程序终止!\\n");
exit(-1); //终止程序
}
/*分配存储最后一个尾结点的指针*/
PNODE pTail = pHead;
pTail->pNext = NULL;
/*用户输入链表的长度*/
printf("请输入您需要生成的链表结点个数:");
scanf("%d", &len);
/*用户输入每一个结点的数据*/
for (i = 0; i < len; i++)
{
printf("请输入第 %d 个结点的值:", i + 1);
scanf("%d", &val);
/*新分配一个结点,用于临时存放用户输入的数据*/
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if (NULL == pNew)
{
printf("分配失败!程序终止!\\n");
exit(-1); //终止程序
}
/*将之后每分配的结点挂在前一个结点后*/
pNew->data = val;
pTail->pNext = pNew;
pNew->pNext = NULL;
pTail = pNew;
}
return pHead; //返回第一个存放有效数据的结点地址
}
/*遍历链表*/
void Traverse_list(PNODE pHead)
{
PNODE p = pHead->pNext; //定义结点的指针,pHead指向的下一个结点地址
/*
判断指向下一个结点地址是否为NULL,是则表明是最后一个结点
否则输出这个结点中的数据部分,并使p指向下一个结点
*/
while(NULL != p)
{
printf("%d ", p->data);
p = p->pNext;
}
printf("\\n");
return;
}
/*判断链表是否为空*/
bool Is_empty(PNODE pHead)
{
/*如果头指针指向的下一个结点为NULL,则表明链表中没有结点*/
if (NULL == pHead->pNext)
return true;
else
return false;
}
/*判断链表的长度*/
int Length_list(PNODE pHead)
{
/*定义临时结点指针p,p指向首结点*/
PNODE p = pHead->pNext;
int len = 0;
/*
判断p是否为空,为空则表明是最后一个结点,否则执行长度+1
同时把p指向下一个结点
*/
while(NULL != p)
{
++len;
p = p->pNext;
}
return len; //返回链表的长度
}
/*向链表的第pos个结点前插入一个新的结点,值为val*/
bool Insert_list(PNODE pHead, int pos, int val)
{
int i = 0;
PNODE p = pHead;
/*
pHead指向一个链表,并且插入的位置要大于0,即只能在1之后的位置插入结点,
包括1,不能在负数位置插入结点
i用来统计链表的长度,插入的位置只能是链表长度的下一个结点,不能
是下下一个结点,即中间不能空一个结点
*/
while(NULL != p && i < pos - 1)
{
p = p->pNext;
i++;
}
/*如果插入结点的位置大于链表长度+1,或p没有指向一个链表,返回false*/
if (i > pos - 1 || NULL == p)
return false;
/*定义一个临时结点,用于存放用户输入的数据*/
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if (NULL == pNew)
{
printf("动态内存分配失败!\\n");
exit(-1);
}
/*将新分配的结点挂在链表上*/
pNew->data = val;
PNODE q = p->pNext;
p->pNext = pNew;
pNew->pNext = q;
return true;
}
/*对链表中的元素进行排序*/
以上是关于数据结构-链表的操作的主要内容,如果未能解决你的问题,请参考以下文章