单链表
单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/964deb5267fe83c84d3b8be0830b7a31.png)
链表的分类
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/e5439eed52a448b33e9dfa9c363148b1.png)
c语言定义单链表
typedef struct node
{
int data;//数据域
struct node *next;//指针域
}node,*pNode;
非循环单链表的基本操作
主函数部分
int main()
{
pNode pHead = NULL;//创建一个头节点
pHead = create_list();//创建一个非循环单链表,并将该链表头节点付给pHead
int len = len_list(pHead);
sort(pHead,len);
insert(pHead,100,2);
delete(pHead, 2);
traverse(pHead);
return 0;
}
(1)链表的创建(尾插法)***
pNode create_list()
{
pNode pHead = (pNode)malloc(sizeof(node));//创建一个不存放有效数据的头节点
int len;
int val;
pNode pTail = pHead;//创建一个节点指向尾部,一开始在头部
pTail->next = NULL;
if (NULL == pHead)
{
printf("内存分配失败\n");
exit(-1);
}
printf("请输入生成的节点数:\n");
scanf_s("%d", &len);
for (int i = 0; i < len; ++i)
{
printf("请输入第%d个节点的值:", i+1);
scanf_s("%d", &val);
pNode pNew = (pNode)malloc(sizeof(node));//创建了一个新的节点
if (NULL == pNew)
{
printf("动态内存分配失败!\n");
exit(-1);
}
pNew->data = val;
pTail->next = pNew;
pNew->next = NULL;
pTail = pNew;
}
return pHead;
}
算法:
1:首先创建一个不存放有效数据的头节点,通过它方便操作整个链表
2:通过尾插法创建新元素
(1)创建一个新的节点pNew,再创建一个指向尾节点的指针pTail,一开始头部即尾部
(2)将要添加的元素的值赋给pNew的数据域
(3)使已有节点与添加的新节点建立联系,即使pTail的指针域指向新节点,因为每一个新节点都插入在最 后,所以使新节点的指针域指向空
(4)将尾指针移向新节点,新节点变为尾节点
(2)链表的遍历
void traverse(pNode pHead)
{
pNode p = pHead;
while (p->next != NULL)
{
p = p->next;
printf("%d ", p->data);
}
printf("\n");
return;
}
(3)求链表长度
int len_list(pNode pHead)
{
int len=0;
pNode p = pHead->next;
while (p != NULL)
{
len++;
p = p->next;
}
return len;
}
(4)排序
void sort(pNode pHead,int len)
{
pNode p, q;
int i, j;
for (i = 0, p = pHead->next; i < len - 1; ++i, p = p->next)
{
for (j = i + 1, q = p->next; j < len; ++j, q = q->next)
{
if (q->data < p->data)
{
int temp = q->data;
q->data = p->data;
p->data = temp;
}
}
}
return;
}
(5)删除
bool delete(pNode pHead, int pos)
{
pNode p = pHead;
int i = 0;
if (is_empty(pHead))
return false;
while (NULL != p && i < pos - 1)
{
++i;
p = p->next;
}
if (NULL == p || i > pos - 1)
return false;
pNode q = p->next;//新建一个q变量,防止删除时p->next丢失
p->next = q->next;
free(q);
q = NULL;
return true;
}
算法:
(1)遍历至删除元素位置前面的位置
(2)如果不满足条件返回false
(3)新建q变量指向要删除的元素
(4)将删除元素前面的元素指针域指向要删除元素的下一个元素
(5)删除元素,使q指向空
(6)插入***
bool insert(pNode pHead, int val, int pos)
{
pNode p = pHead;
int i = 0;
while (NULL != p && i < pos - 1)
{
++i;
p = p->next;
}
if (NULL == p || i > pos)
return false;
pNode pNew = (pNode)malloc(sizeof(node));
if (NULL == pNew)
{
printf("动态内存分配失败!\n");
exit(-1);
}
pNew->data = val;
pNode q = p->next;
pNew->next = q;
p->next = pNew;//如果没有定义q变量这两句话的位置不能交换
return true;
}
算法:
(1)先遍历元素至添加元素位置的前一个,如果不满足条件返回false
(2)开辟新的节点空间
(3)使新建节点的指针域指向原先插入位置的元素,再插入位置前的元素指针域指向新节点
(或者创建一个新的变量指向插入位置的前一元素,可将两句话位置交换)