数据结构----单链表的创建、插入、删除、读取、遍历
2018-02-07 17:21
447 查看
阅读《大话数据结构》关于链表的章节后,自己尝试写出了链表的几个函数,在微博进行记录。
代码如下:
#include <stdio.h>
#include <malloc.h>
//创建链表结构体
typedef struct Node
{
int data;
struct Node *next;
}Node;
typedef Node* LinkList; //定义LinkList的数据类型为Node*
//尾插法创建链表,表头后有n个结点
void CreateListHead(LinkList *L,int n)
{
int i;
LinkList p, q;
*L = (LinkList)malloc(sizeof(Node)); //申请头结点的内存空间
p = *L;
p->data = n; //头结点数据域,存储链表的数据的长度
for (i = 0; i < n; i++)
{
q = (LinkList)malloc(sizeof(Node));
q->data = i+1; //给新建的结点的数据域赋值
p->next = q; //末尾结点的指针域指向新创建的结点
p = q; //p指针缓存q的地址,下一循环中p->next,即为q->next,使本循环中q的指针域指向下一结点
}
p->next = NULL; //尾结点指针域为空
}
//获取链表中第i个结点的数据并返回给e,i为0取的是头结点数据域(除头结点外,结点的个数)
int GetElem(LinkList L,int i,int* e)
{
LinkList p;
p = L;
while(p && i--) //找到第i个结点
{
p = p->next;
}
if(!p) return 0; //第i个结点为空,报错
*e = p->data; //将第i个结点的数据赋值给*e
return !0;
}
//在链表头结点后第i个结点位置插入一个节点,数据域为e,原结点后移
int ListInsert(LinkList *L,int i,int e)
{
LinkList p,q;
if ( i < 1) return 0; //i为0,报错
q = *L;
while (q && --i) //寻找第i-1个结点的位置
{
q = q->next;
}
if (!q) return 0; //i-1结点为空,报错
p = (LinkList)malloc(sizeof(Node)); //p申请内存空间,应在找到i-1结点后申请,否则可能因报错浪费内存空间
p->next = q->next; //新建结点的指针域 = i-1位置结点的指针域
q->next = p; //i-1位置结点的指针域指向新建的结点
p->data = e; //新建结点的数据域为e
(*L)->data++; //链表长度+1
return !0;
}
//删除链表头结点后第i个结点,并将该结点数据返回给*e
int ListDelete(LinkList *L,int i,int* e)
{
LinkList p, q;
if (i < 1) return 0; //i为0,报错
q = *L;
while (q && --i) //寻找第i-1结点
{
q = q->next;
}
if (!q->next) return 0; //i-1结点指针域为空,即第i个结点不存在,报错
p = q;
p = p->next; //p为第i个结点
*e = p->data; //将第i个结点的数据返回给*e
q->next = p->next; //将i-1结点的指针域变为第i个结点的指针域
free(p); //释放第i结点的内存
(*L)->data--; //链表长度减一
return !0;
}
//遍历链表数据(包括头结点)
void PrintfList(LinkList L)
{
LinkList p;
p = L; //直接遍历链表L,会使L不再指向头结点
while (p) //当L为NULL时,停止打印DATA
{
printf("%d\n", p->data);
p = p->next;
}
}
main()
{
int temp;
LinkList L;
CreateListHead(&L, 5); //创建一个链表,头结点后有5个结点
printf("创建的链表为:\n");
PrintfList(L);
if (ListInsert(&L, 6, 100)) //在第6个结点位置插入数据为100的结点
{
printf("在第6个结点位置插入结点后链表为:\n");
PrintfList(L);
}
else
{
printf("在第6个结点位置插入结点失败\n");
}
if (ListDelete(&L, 1, &temp)) //删除头结点后第1个结点
{
printf("删除第1结点后链表为:\n");
PrintfList(L);
printf("删除的结点的数据为:%d\n", temp);
}
else
{
printf("删除第1结点失败\n");
}
if (GetElem(L, 4, &temp)) //读取头结点后第4个结点的数据
{
printf("读取头结点后第4个结点数据为:\n");
printf("%d\n", temp);
}
else
{
printf("读取头结点后第4个结点数据失败\n");
}
getch(); //等待用户按键
}
编译的环境为VS2015,运行结果如下图:
这里需要注意的是,传递进函数里面的结构体指针变量,是传递它本身还是传递它的地址。
如:CreateListHead();函数,如果传递进去的不是&L而是L,是无法创建成功链表的。
具体参考:http://blog.csdn.net/a3748622/article/details/79286974
代码如下:
#include <stdio.h>
#include <malloc.h>
//创建链表结构体
typedef struct Node
{
int data;
struct Node *next;
}Node;
typedef Node* LinkList; //定义LinkList的数据类型为Node*
//尾插法创建链表,表头后有n个结点
void CreateListHead(LinkList *L,int n)
{
int i;
LinkList p, q;
*L = (LinkList)malloc(sizeof(Node)); //申请头结点的内存空间
p = *L;
p->data = n; //头结点数据域,存储链表的数据的长度
for (i = 0; i < n; i++)
{
q = (LinkList)malloc(sizeof(Node));
q->data = i+1; //给新建的结点的数据域赋值
p->next = q; //末尾结点的指针域指向新创建的结点
p = q; //p指针缓存q的地址,下一循环中p->next,即为q->next,使本循环中q的指针域指向下一结点
}
p->next = NULL; //尾结点指针域为空
}
//获取链表中第i个结点的数据并返回给e,i为0取的是头结点数据域(除头结点外,结点的个数)
int GetElem(LinkList L,int i,int* e)
{
LinkList p;
p = L;
while(p && i--) //找到第i个结点
{
p = p->next;
}
if(!p) return 0; //第i个结点为空,报错
*e = p->data; //将第i个结点的数据赋值给*e
return !0;
}
//在链表头结点后第i个结点位置插入一个节点,数据域为e,原结点后移
int ListInsert(LinkList *L,int i,int e)
{
LinkList p,q;
if ( i < 1) return 0; //i为0,报错
q = *L;
while (q && --i) //寻找第i-1个结点的位置
{
q = q->next;
}
if (!q) return 0; //i-1结点为空,报错
p = (LinkList)malloc(sizeof(Node)); //p申请内存空间,应在找到i-1结点后申请,否则可能因报错浪费内存空间
p->next = q->next; //新建结点的指针域 = i-1位置结点的指针域
q->next = p; //i-1位置结点的指针域指向新建的结点
p->data = e; //新建结点的数据域为e
(*L)->data++; //链表长度+1
return !0;
}
//删除链表头结点后第i个结点,并将该结点数据返回给*e
int ListDelete(LinkList *L,int i,int* e)
{
LinkList p, q;
if (i < 1) return 0; //i为0,报错
q = *L;
while (q && --i) //寻找第i-1结点
{
q = q->next;
}
if (!q->next) return 0; //i-1结点指针域为空,即第i个结点不存在,报错
p = q;
p = p->next; //p为第i个结点
*e = p->data; //将第i个结点的数据返回给*e
q->next = p->next; //将i-1结点的指针域变为第i个结点的指针域
free(p); //释放第i结点的内存
(*L)->data--; //链表长度减一
return !0;
}
//遍历链表数据(包括头结点)
void PrintfList(LinkList L)
{
LinkList p;
p = L; //直接遍历链表L,会使L不再指向头结点
while (p) //当L为NULL时,停止打印DATA
{
printf("%d\n", p->data);
p = p->next;
}
}
main()
{
int temp;
LinkList L;
CreateListHead(&L, 5); //创建一个链表,头结点后有5个结点
printf("创建的链表为:\n");
PrintfList(L);
if (ListInsert(&L, 6, 100)) //在第6个结点位置插入数据为100的结点
{
printf("在第6个结点位置插入结点后链表为:\n");
PrintfList(L);
}
else
{
printf("在第6个结点位置插入结点失败\n");
}
if (ListDelete(&L, 1, &temp)) //删除头结点后第1个结点
{
printf("删除第1结点后链表为:\n");
PrintfList(L);
printf("删除的结点的数据为:%d\n", temp);
}
else
{
printf("删除第1结点失败\n");
}
if (GetElem(L, 4, &temp)) //读取头结点后第4个结点的数据
{
printf("读取头结点后第4个结点数据为:\n");
printf("%d\n", temp);
}
else
{
printf("读取头结点后第4个结点数据失败\n");
}
getch(); //等待用户按键
}
编译的环境为VS2015,运行结果如下图:
这里需要注意的是,传递进函数里面的结构体指针变量,是传递它本身还是传递它的地址。
如:CreateListHead();函数,如果传递进去的不是&L而是L,是无法创建成功链表的。
具体参考:http://blog.csdn.net/a3748622/article/details/79286974
相关文章推荐
- 数据结构学习二 数据结构之链表图解版【创建,遍历,删除,插入】
- 数据结构单链表插入\整表删除\整表创建\
- 数据结构顺序表的操作全集(创建,遍历,插入,删除,排序等等)
- 数据结构——单链表的创建、删除、遍历以及节点的插入、删除等操作
- 数据结构—链表的定义、创建、遍历、插入、删除
- 单链表的基本操作(创建、删除、插入、遍历)
- 单链表操作,创建,遍历,插入,删除,排序等操作
- 数据结构 图 创建 插入 遍历 删除 销毁
- 单链表创建-遍历-排序-插入-删除-逆序操作
- 单链表的创建、遍历、插入、删除、查找、逆转
- C语言单链表的创建、插入、查找、删除、求长、排序、遍历
- C++单链表的操作(创建,删除,打印,遍历,插入)
- 数据结构链表创建,遍历,是否为空,求长度,插入,删除算法的演示
- 数据结构 单链表的创建 插入 删除
- C语言进阶-第18讲:单链表的遍历、创建、插入和删除结点
- C++单链表的动态创建,查找,遍历,删除,插入,添加,排序
- 数据结构学习二 数据结构之链表代码版【创建,遍历,删除,插入】
- 数据结构——栈的构造、插入、删除、读取操作程序
- 单向链表的创建、遍历、求长、判存、判空、插入、删除、查找(按位置或元素)、合并
- 数据结构:头插法、尾插法创建单链表,求链表长度、查找、插入、删除、合并