从零开始写一个单向不循环链表
总结:郝斌数据结构与算法课程
数据结构概述:
定义:
我们如何把现实中大量的而复杂的问题以特定的数据类型和特定的存储结构保存到主存储器(内存)中,以及在此基础上为实现某个功能,(比如查找某个元素,删除某个元素,对所有的元素的进行排序)
数据结构= 个体的存储 + 个体的关系存储
算法:对存储数据的操作。
再次讨论什么是数据结构?
狭义:数据结构是专门研究数据存储问题的课程。
数据存储包含两个方面:个体的存储+ 个体关系的存储
广义:
数据结构即包含数据的存储也包含数据的操作。
对存储数据的操作就是算法。
1、最简单链表的数据结构
typedef struct Node
{
int sid; //数据域
struct Node *pNext; //指针域
}NODE,*PNODE;
首先我们链表和数组都是连续存储的数据类型
但是我们链表在空间上是离散分配的。
为什么使用struct Node *pNext;此数据类型。
因为我们需要使用指针域去寻找下一个指针结点的值。
2、如何创建一个链表和遍历一个链表
//为什么我们需要动态分配内存,而不是使用局部指针呢?
在pHead头指针中,我们使用动态分配的目的就是为了实现跨函数使用内存。
因为我们的尾结点就是一个局部函数操作的,不需要除此函数之外的函数使用这段内存空间,所以我们不需要动态分配内存。
PNODE create_list(void)
{
int i=0;
int len;
int val;
PNODE pHead = (PNODE)malloc(sizeof(NODE));
if(NULL == pHead)
{
printf("pHead is create error\n");
exit(-1);
}
//定义一个尾节点,因为尾节点是需要局部变量的
PNODE pTail = pHead;
pTail->pNext = NULL;
printf("请输入你需要创建的链表的长度");
scanf("%d",&len);traverse_list(pHead);
for(i=0; i<len; i++)
{
printf("请输入你第%d个数据",i+1);
scanf("%d",&val);
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if(NULL == pNew)
{
printf("pNew is error");
exit(-1);
}
pNew->sid = val;
pTail->pNext = pNew;
pNew->pNext = NULL;
pTail = pNew;
}
return pHead;
}
void traverse_list(PNODE pHead)
{
PNODE pNew = pHead->pNext;
while(pNew != NULL)
{
printf("%d",pNew->sid);
pNew = pNew->pNext;
}
printf("\n");
}
2、插入链表和删除链表
除了代码的注释方面的知识外,最关键就是错误的判断和无论是插入或者是删除函数,我们都需要知道你需要插入或者删除的节点的上一个节点的地方,这样才能进行操作。
//第一个参数是你要操作的链表,第二个参数的是你要插入的位置,第三个参数是插入的数据
int insert_list(PNODE pHead, int pos, int val)
{
int i = 0;
//定义一个局部变量,是用来遍历的所以我们需要使用局部变量就可以了。
PNODE p = pHead;
//这句代码的意思就是我们的p节点不能是空指针,我们遍历的链表不能小于pos的长度
while( NULL != p && i < pos-1)
{
p=p->pNext;
i++;
}
//任何时候p的值指向空指针就是错误的,还有i的计数大于pos-1不符合我们的要求
if(NULL == p || i > pos-1)
return -1;
//因为我们需要插入一段内存,我们需要使用一段动态内存。这趟我们就可以跨函数使用内存
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if(NULL == pNew)
{
printf("pNew error\n");
exit(-1);
}
pNew->sid = val;
PNODE q = p->pNext;
p->pNext = pNew;
pNew->pNext = q;
return 0;
}
int delete_list(PNODE pHead, int pos, int* val)
//int delete_list(PNODE pHead, int pos)
{
int i = 0;
//定义一个局部变量,是用来遍历的所以我们需要使用局部变量就可以了。
PNODE p = pHead;
//这句代码的意思就是我们的p节点不能是空指针,我们遍历的链表不能小于pos的长度
while( NULL != p && i < pos-1)
{
p=p->pNext;
i++;
}
//任何时候p的值指向空指针就是错误的,还有i的计数大于pos-1不符合我们的要求
if(NULL == p->pNext || i > pos-1)
return -1;
//因为我们需要插入一段内存,我们需要使用一段动态内存。这趟我们就可以跨函数使用内存
PNODE q = p->pNext;
*val = q->sid;
p->pNext = p->pNext->pNext;
free(q);
q=NULL;
return 0;
}