单链表的基本操作实现
先说点题外话:本科是一所双非院校,因为已经在准备考研了,所以不得不回头重新拿起这些最基本的数据结构知识,每重新看一次都会有一些新的理解,因为在校期间说实话数据结构这些基本知识确实学的不好,曾经有一段时间一直在逃避,可能不如其他大佬那么精简,但是后来发现计算机这一行算法是逃不掉的,加上从入学就一直想考研,重新买了王道的书,一点一点的扣这些基本算法,希望能把每个点吃透,也让别人看的舒服一点,实践远大于理论,这是我学这个专业最为赞同的一句话,无论什么时候都要实操这些东西,所以本着这些我一次又一次在机器上跑这些代码,就是为了让自己的知识更为扎实牢固一点,希望我的努力能或多或少帮助到你。
这些算法都是基于带头结点的链表实现的,因为时间有限,所以不带头结点的就不放上来了,当然很多操作可能有我没想到的地方,或许可以变形更为精简,如有错误欢迎各位批评指正
1.初始化单链表
//单链表的初始化
int InitList(LinkList* L) //引用类型指针形参//
{
(*L) = (LinkList)malloc(sizeof(LNode)); //头结点分配空间//
(*L)->next = NULL; //头结点指针域置空//
if (L)
printf("Finish\n");
else
printf("Error\n");
return Ok;
}
2.头插法创建单链表
int CreateList_1(LinkList* L, int n) //引用类型指针形参//
{
printf("逆序输入\n");
int i;
LinkList p;
(*L) = (LinkList)malloc(sizeof(LNode));
(*L)->next = NULL;
for (i = n; i > 0; i--)
{
p = (LNode*)malloc(sizeof(LNode));
scanf("%d", &p->data);
p->next = (*L)->next;
(*L)->next = p;
}
return Ok;
}
3.尾插法创建单链表
//尾插法构建链表//
int CreateList_2(LinkList* L, int n) //引用类型指针形参//
{
int i;
printf("正序输入\n");
LinkList p, r;
(*L) = (LinkList)malloc(sizeof(LNode));
(*L)->next = NULL;
r = (*L);
for (i = 0; i < n; i++)
{
p = (LinkList)malloc(sizeof(LNode));
scanf("%d", &p->data);
p->next = NULL;
r->next = p;
r = p;
}
return Ok;
}
4.按位查找单链表
//按位序查找
int GetElem2(LinkList L, int i)
{
LNode* p = L;
if (i < 0)
printf("查找位置不合法,查找失败!");
int j = 0;
while (p != NULL && j < i)
{
p = p->next;
j++;
}
return p;
}
5.按值查找
//按值查找
int GetElem(LinkList L, int i, Elemtype* e)
{
int j;
LinkList p; /* 声明一结点p */
p = L->next; /* 让p指向链表L的第一个结点 */
j = 1; /* j为计数器 */
while (p && j < i) /* p不为空或者计数器j还没有等于i时,循环继续 */
{
p = p->next; /* 让p指向下一个结点 */
++j;
}
if (!p || j > i)
return Error; /* 第i个元素不存在 */
*e = p->data; /* 取第i个元素的数据 */
return Ok;
}
6.单链表的插入操作
//单链表的插入(按位序插入)
int InsertList(LinkList L, int i, Elemtype e)
{
if (i < 1)
printf("插入位置非法,插入失败!");//这里的插入是按照位置插入,并非结点下标值。所以从第一个位置插入
LNode* p, * x;
p = L;
int j = 0;//头节点为第0个结点,没有数据
while (p!=NULL&&j<i-1)//遍历找到插入位置的前一个元素
{
p = p->next;
j++;
}
if (!p || j > i - 1)
return Error;
x = (LNode*)malloc(sizeof(LNode));
x->data = e;
x->next = p->next;
p->next = x;
printf("插入数据成功");
}
7.单链表的删除
//单链表的删除操作
int DeleteNode(LinkList L, int i, Elemtype e)
{
LNode* p = L;
//找到待删除节点的前驱结点,让前驱结点指向待删除节点的后继节点。释放结点内存空间
int j = 0;
while (p != NULL&&j<i-1)
{
p = p->next;
j++;
}
if (!p || j > i - 1)//删除位置不合法
return Error;
LNode* q = p->next;//q指向被删除结点
p->next = q->next;
e = q->data;
free(q);
}
8.单链表的逆置
//单链表的逆置
void Travserve(LinkList L)
{
LinkList p = L->next;
L->next = NULL;
LinkList q;
while (p)
{
q = p->next;
p->next = L->next;
L->next = p;
p = q;
}
}
9.利用后插实现结点的前插
//前插操作的变形,
int PriorInsert(LinkList *L, int i,LNode* p, LNode* s)//s为待插入节点,
{
//调用查找函数先找到插入该结点的前驱结点
GetElem2(L, i);//查找p结点
s->next = p->next;
p->next = s;
//交换数据域
Elemtype temp=p->data;
p->data = s->data;
s->data = temp;
printf("插入成功");
}
10.清空单链表
//清空单链表
void clear(LinkList L)
{
LinkList p, q;
p = L->next;
while (p)
{
q = p->next;
free(p);
p = q;
}
L->next = NULL;
printf("链表已清空");
}
11.判空操作
//判空
void Empty(LinkList L)
{
if (L->next == NULL)
{
printf("链表为空链表");
}
else {
printf("链表不为空");
}
}