数据结构之链表篇
所有代码均出自郝斌老师数据结构教学视频
单链表的学习过程,我们需要明白几个重要定义:
头指针:
头结点:
首结点(第一个结点):
尾结点:
抽象链表的数据结构
typedef struct Node
{
int data;
struct Node* pNext;
}Node;//NODE 等价于struct NODE PNODE等价于struct Node*
typedef struct Node* PNODE;
typedef struct Node NODE;
主要链表的操作及其函数的声明
PNODE create_list(void); //创建链表
void traverse_list(PNODE pHead); //遍历链表至输出
bool is_empty(PNODE pHead); //判断链表是否为空链表
int length_list(PNODE pHead); //链表长度求解函数
void sort_list(PNODE pHead); //链表的数据排序
bool inset_list(PNODE pHead, int pos, int val); //插入指定元素
bool delete_list(PNODE pHead, int pos, int *pVal); //删除指定元素
模块一:创建链表的操作:
操作条件:
输入参数:无输入参数
输出参数:头指针pHead
PNODE creat_list(void)
{
int len,i,val; //len为结点个数,val用来临时存放用户输入的终点的值
PNODE pHead = (PNODE)malloc(sizeof(NODE)); //分配一个不存放有效数据的头结点
if (NULL==pHead) //为了判断动态分配内存是否成功
{
printf("分配失败,程序终止!\n");
exit(-1);
}
PNODE pTail = pHead; //声明一个尾结点,尾结点和头结点为同一个结点
pTail->pNext = NULL; //由于尾结点的指针域为NULL
printf("请设置链表的结点的个数:len="); //设置结点的长度
scanf_s("%d",&len);
for ( i = 0; i < len; i++) //应用循环产生结点
{
printf("请输入第%d个结点:",i+1);
scanf_s("%d",&val);
PNODE pNew = (PNODE)malloc(sizeof(NODE)); //每循环一次,就需要动态分配一个新的结点
if (pNew == NULL)
{
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; //定义一个结点P,将头结点的指针域(指向首结点/第一个有效结点)赋值给P
while(NULL!=P)
{
printf("%d\t",p->data); //输出相应结点的有效数据
p = p->pNext; //将当前p的指针域赋值给p,那么p变成下一个结点。(不是连续的,不能应用p++)
}
printf("\n");
return;
}
bool is_empty(PNODE pHead)
{
if (pHead->pNext==NULL) //如果头结点的指针域都是空,那么链表为空
return true;
else
return false;
}
链表长度求解函数
int length_list(PNODE pHead)
{
PNODE p=pHead->pNext; //p就是首结点
int len = 0;
while(NULL!=P)
{
len++;
p = p->pNext;
}
return len;
}
单链表的插入操作:
- 声明一个结点p指向链表的头结点
- 判断pos的位置,如果i<pos就遍历链表,让p的指针向后移动,指向下一个结点,i从0开始
- 若到链表p末尾还未空,则说明pos不合理
- 查找成功,声明一个新的空结点,动态分配内存
- 将插入数据元素赋值给新结点的数据域
- 执行单链表的插入标准语句,将p结点的指针域赋值给q结点的指针域,将q结点的地址赋值给p的指针域。
- 返回成功
bool inset_list(PNODE pHead, int pos, int val)
{
int i = 0;
PNODE p = pHead;
while (NULL != p && i < pos - 1) {
p = p->pNext;
++i;
}
if (i>pos-1||NULL==p)
return false;
PNODE pNew = (PNODE)malloc(sizeof(NODE));
pNew->data = val;
PNODE q = p->pNext;
p->pNext = pNew;
pNew->pNext = q;
return true;
}
链表指定删除数据元素操作
q的作用在于释放内存,避免内存的泄露
bool delete_list(PNODE pHead, int pos, int *pVal)
{
int i = 0;
PNODE p = pHead;
while (NULL != p && i < pos - 1) {
p = p->pNext;
++i;
}
if (i > pos - 1 || NULL == p)
return false;
PNODE q = p->pNext;
*pVal = q->data;
p->pNext = p->pNext->pNext;
free(q);
q = NULL;
}
链表的排序
void sort_list(PNODE pHead)
{
int i, j, t;
int len = length_list(pHead);
PNODE p, q;
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)
{
if (p->data > q->data)
{
t = p->data;
p->data = q->data;
q->data = t;
}
}
}
}