链表
链表为离散存储的数据结构。由n个节点离散分配,彼此通过指针相连,每个节点只有一个前驱节点和后驱节点,首节点没有前驱节点,尾节点没有后驱节点。
关键概念:
-
首节点:
第一个有效节点
-
尾节点:
最后一个有效节点
-
头节点:
第一个有效节点前的那个节点
头节点不存放有效数据
加头节点的目的主要是为了方便对链表的操作
-
头指针:
指向头节点的指针变量
-
尾指针:
指向尾节点的指针变量
链表的优缺点:
-
优点
空间没有限制
插入删除元素较快
-
缺点
存取速度很慢
实现链表元素的插入和删除算法(伪代码):
-
插入:
- r=p->pNext; p->pNext=q; q=r->pNext;
- q->pNext=p->pNext; p->pNext=q;
-
删除:
//直接让第一个节点指向第三个节点去删除第二个节点元素,
//会使得第二个节点的内存无法释放,从而内存泄漏
r=p->pNext;
p-pNext=r->pNext;
free®;//释放r,防止内存泄漏
初始化创建列表、长度计算、排序、插入、删除、显示的函数实现过程:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
typedef struct Node
{
int data;
struct Node* pNext;
}NODE,*PNODE;
PNODE create_list(void);
void traverse_list(PNODE phead);
void insert_list(PNODE phead, PNODE ins,int pos);
void delete_list(PNODE phead, int pos);
int length_list(PNODE phead);
void sort_list(PNODE phead);//选择排序算法
int main(void)
{
int pos;
int val;
int pos_delete;
PNODE phead = NULL;
phead = create_list();
traverse_list(phead);
sort_list(phead);
traverse_list(phead);
printf("请输入需要插入的位置和数值:\n");
scanf_s("%d",&pos);
scanf_s("%d", &val);
NODE in = { val,NULL };
PNODE insert=∈
//insert->data = 90;
//insert->pNext = NULL;
insert_list(phead,insert,pos);
traverse_list(phead);
printf("输入需要删除的节点位置:\n");
scanf_s("%d",&pos_delete);
delete_list(phead,pos_delete);
traverse_list(phead);
printf("链表的长度是:%d \n",length_list(phead));
return 0;
}
PNODE create_list(void)
{
int len;
int i;
int val;
printf("请输入需要链表的长度:\n");
scanf_s("%d",&len);
PNODE phead = (PNODE)malloc(sizeof(NODE));
if (phead == NULL) {
printf("初始化节点失败!\n");
exit(-1);
}
PNODE pTail = phead;//创建一个每次链表尾,在pNew新建一个数据后,用它不停的更新数据
pTail->pNext = NULL;//初始化尾节点的指针(单链表尾节点的指针域为空)
for (i = 0; i < len; ++i) {
printf("please inpute %d number: \n",i+1);
scanf_s("%d",&val);
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if (pNew == NULL) {
printf("初始化节点失败!\n");
exit(-1);
}
else
{
pNew->data = val;//下一个节点得到数据
pTail->pNext = pNew;//之前的尾节点指针域(pTail)更新为新尾节点(pNew)位置
pNew->pNext = NULL;//新尾节点的指针域改为NULL;此时前尾节点的指针域指向新的尾节点,新的尾节点完成数据更新
pTail = pNew;//pNew变成新的尾节点pTail
}
}
return phead;
}
void traverse_list(PNODE phead)
{
if (phead->pNext == NULL)
printf("链表为空!\n");
else
{
PNODE p = phead->pNext;
while (p!=NULL)
{
printf("%d ",p->data);
p = p->pNext;
}
printf("\n");
}
}
int length_list(PNODE phead)
{
int len = -1;//因为从头节点开始计数的
if (phead->pNext == NULL)
printf("链表为空!\n");
else
{
while (phead!=NULL)
{
len++;
phead = phead->pNext;
}
}
return len;
}
void insert_list(PNODE phead,PNODE ins,int pos)
{
int i;
if (phead->pNext == NULL)
printf("链表为空!\n");
else if(0 < pos&&pos < length_list(phead)+2)
{
PNODE pN = NULL;
for (i = 1; i < pos; ++i) {
phead = phead->pNext;//得到前一个节点信息
}
pN = phead->pNext;//得到下一个节点信息
ins->pNext = pN;
phead->pNext = ins;
}
else
{
printf("该位置不存在或操作违法!\n");
}
return;
}
void delete_list(PNODE phead, int pos)
{
int i;
if (phead->pNext == NULL)
printf("链表为空!\n");
else if (0 < pos &&pos < length_list(phead))
{
PNODE pN,pNN;
for (i = 1; i < pos; ++i) {
phead = phead->pNext;//得到前一个节点的信息
}
pN = phead->pNext;
pNN = pN->pNext;
phead->pNext = pNN;
free(pN);
}
else
{
printf("该位置不存在!\n");
}
return;
}
void sort_list(PNODE phead)
{
int i,j,len,r;
len = length_list(phead);
if (phead->pNext == NULL)
printf("链表为空!\n");
else
{
PNODE p,pN;
p = phead->pNext;
pN = p->pNext;
for (i = 0; i < len-1; ++i) {
for (j = i+1; j < len; ++j) {
if (p->data > pN->data)
{
//使用链表中的值域完成对链表的排序,比修改指针域快捷
r = p->data;
p->data = pN->data;
pN->data = r;
}
pN = pN->pNext;
}
p = p->pNext;
pN = p->pNext;
}
}
return;
}