目录
一、前言
上一章我们写了线性表的顺序存储结构,应该也可以理解为一种静态数据结构(Static Data Structure),即事先分配好空间,在逻辑上相邻的两个元素在物理位置上也相邻,可以随机存取任意元素,在插入、删除操作时,需要大量移动元素,且效率低下。因此本章来写写另一种结构,动态数据结构(Dynamic Data Structure),也叫线性表的链式存储结构——单链表
二、头文件
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int ElemType;//重命名
//-----------线性表的单链表存储结构-----------
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode, *LinkList;
void Init_LinkList(LinkList *head);//初始化
void Create_LinkList(LinkList *head);//创建链表
void Show_LinkList(LinkList *head);//显示链表(遍历)
int Length_LinkList(LinkList *head);//链表长度
void Insert_LinkList(LinkList *head, ElemType x, int pos);//按位置插入元素
void Delete_LinkList(LinkList *head, int pos);//按位置删除元素
void Sort(LinkList *head); //排序法(非递减)
void Merge_LinkList(LinkList p1, LinkList p2, LinkList *p3);//合并两个链表
void Reverse(LinkList *head);//单链表逆置(递归)
LNode* Reverse(LNode *p); //相当于给了个封装
//------------- 排序算法以后会优化 ---------------
三、各种功能的实现
1、初始化
//初始化
void Init_LinkList(LinkList *head)
{
*head = (LinkList)malloc(sizeof(LinkList));
assert(*head != NULL);
(*head)->next = NULL;
}
2、创建链表
//创建链表
void Create_LinkList(LinkList *head)
{
LNode *p = *head;
int item;
printf("请输入数据(以-1结束):");
while (scanf("%d", &item) ,item != -1)
{
LNode *s = (LNode*)malloc(sizeof(LNode));
assert(s != NULL);
s->next = NULL;
s->data = item;
p->next = s;
p = s;
}
}
3、遍历
//显示链表(遍历)
void Show_LinkList(LinkList *head)
{
LNode *p = (*head)->next;
while (p)
{
printf("%d->", p->data);
p = p->next;
}
printf("NULL.\n");
}
4、求长度
//链表长度
int Length_LinkList(LinkList *head)
{
LNode *p = (*head)->next;
int i = 0;
while (p)
{
p = p->next;
i++;
}
return i;
}
5、按位置插入
//按位置插入元素
void Insert_LinkList(LinkList *head, ElemType x, int pos)
{
LNode *p = *head; //在单链表的pos位置之前插入元素x
int i = 0;
while (p&&i < pos - 1) //寻找位置pos-1
{
p = p->next;
i++;
}
if (!p || i>pos - 1)
{
printf("插入位置非法...\n");
return;
}
LNode *s = (LNode*)malloc(sizeof(LNode));
assert(s!= NULL);
s->data = x;
s->next = p->next;
p->next = s;
}
6、按位置删除
//按位置删除元素
void Delete_LinkList(LinkList *head, int pos)
{
LNode *p = *head;
int i = 0;
while (p&&i < pos - 1) //寻找位置pos-1
{
p = p->next;
i++;
}
if (!p || i>pos - 1)
{
printf("插入位置非法...\n");
return ;
}
LNode *q = p->next;
p->next = q->next;
free(q);
}
7、非递减排序
//排序(非递减)
void Sort(LinkList *head)
{
LNode *p, *q;
p = (*head)->next;
if (p != NULL)
{
q = p->next;
}
else
{
printf("无法进行排序...\n");
return;
}
for (p; p != NULL; p = p->next)
{
for (q; q != NULL; q = q->next)
{
if (p->data > q->data)
{
int temp = p->data;
p->data = q->data;
q->data = temp;
}
}
q = p->next;
}
}
8、合并两个单链表
//合并两个单链表
void Merge_LinkList(LinkList p1, LinkList p2, LinkList *p3)
{
//Sort(&p1); //以非递减排序单链表
//Sort(&p2); //以非递减排序单链表
LNode *pa, *pb, *pc;
pa = p1->next;
pb = p2->next;
pc = *p3;
while (pa&&pb)
{
if (pa->data > pb->data)
{
pc->next = pb;
pc = pb;
pb = pb->next;
}
else
{
pc->next = pa;
pc = pa;
pa = pa->next;
}
}
pc->next = pa ? pa : pb;//插入剩余段
}
9、单链表逆置(递归)
//单链表逆置(递归)
void Reverse(LinkList *head)
{
LNode *p = *head;
while (p->next)
{
p = p->next; //过去最后一个结点
}
Reverse((*head)->next);
(*head)->next->next = NULL;
(*head)->next = p;
}
LNode* Reverse(LNode *p)
{
if (p == NULL || p->next == NULL)
{
return p; //找到最后一个结点
}
LNode *s = Reverse(p->next);
s->next = p; //将结点的指向反向
p->next = NULL;
return p;
}
四、主函数测试结果
int main()
{
LinkList List_1, List_2, List_3;
Init_LinkList(&List_1);
Init_LinkList(&List_2);
Init_LinkList(&List_3);
printf("表1:");
Create_LinkList(&List_1);
printf("表2:");
Create_LinkList(&List_2);
printf("\n表1:");
Show_LinkList(&List_1);
printf("表2:");
Show_LinkList(&List_2);
Sort(&List_1); //以非递减排序单链表
Sort(&List_2); //以非递减排序单链表
printf("\n排序后:\n");
printf("表1:");
Show_LinkList(&List_1);
printf("表2:");
Show_LinkList(&List_2);
printf("\n合并单链表:");
Merge_LinkList(List_1, List_2, &List_3);
Show_LinkList(&List_3);
printf("\n按位置插入(pos=4,x=20):");
Insert_LinkList(&List_3,20,4);
Show_LinkList(&List_3);
printf("\n按位置删除(pos=4):");
Delete_LinkList(&List_3, 4);
Show_LinkList(&List_3);
printf("\n单链表逆置:");
Reverse(&List_3);
Show_LinkList(&List_3);
printf("\n长度:");
int len = Length_LinkList(&List_3);
printf("%d", len);
return 0;
}