三种链表的定义和基本操作
单链表
不可随机存取
定义及初始化 判空
注意:
LNode 是强调返回的是一个结点
LinkList 是强调返回的是一个链表
不带头节点的单链表
头指针L指向的是实际的元素结点,即指向实际的值
typedef struct LNode
{
int data;
struct LNode *next;
}LNode,*LinkList;
//初始化
bool InitList(LinkList &L) //注意这里L前面要加&,因为值需要带回
{
L = NULL;
return true;
}
//判空
bool Empty(LinkList L) //此处L前不用&
{
return (L==NULL);
}
带头结点的单链表
初始化
- 分配一个结点,类型是LNode,称为头结点,头指针指向头结点
- 判断分配是否成功
- 头结点后无结点
//带头结点初始化
bool InitList(LinkList &L)
{
L = (LNode *)malloc(sizeof(LNode)); //分配一个头结点
if(L==NULL) return false; //内存不足,分配失败
L->next = NULL;
return ture;
}
//判空
bool Empty(LinkList L)
{
return (L->next ==NULL);
}
查找
按位查找GetElem(L,i)
找到第i个结点
- 判断i是否合法
- 定义一个指针p(指向扫描到的结点
- 定义 j 为指向结点的位置
- 让p先指向头结点
- 用while循环,实现p向后移直到找到i位置结点
//带头结点
bool GetElem(LinkList L, int i)
{
if(i<1) return false;
LNode *p; //指针p指向当前扫描到的结点
int j=0; //当前p指向结点是第几个
p = L; //L指向头结点,即第0个结点(不存数据)
while([p!=NULL&&j<i])
{
p = p->next;
j++;
}
return p;
}
按值查找LocateElem(L,e)
LNode * LocateElem(LinkList L, int e)
{
LNode *p = L->next; //从第一个结点开始查
while(p!=NULL&&p->data!=e)
p = p->next;
return p;
}
插入
后插操作InsertNextNode(p,e)
在P结点后插入值为e的结点
- 判断p结点存不存在
- 申请一个结点s
- 先把e的值给s
- s指向p的下一结点
- p指向s
bool InsertNextNode (LNode *p, int e)
{
if(p==NULL)
return false; //p结点不存在,因为找到p结点要调用GeteLem函数,*p可能为NULL
LNode * s = (LNode *)malloc(sizeof(LNode));
if(s==NULL) return false; //内存分配失败
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
前插操作InsertPriorNode(p,s)
在p结点前插入结点s
- s后插在p后
- 将s和p的数据值交换
bool InsertPriorNode(LNode *p,LNode *s)
{
if(P==NULL||s==NULL) return false;
s->next = p->next;
p->next = s;
int temp = p->data;
p->data = s->data;
s->data = temp;
return true;
}
按位插入 ListInsert(L,i,e)
带头结点
在i位置插入值为e的结点
LNode *p = GetElem(L,i-1); //找到第i-1个结点
return InsertNextNode(p,e) //后插
不带头结点
在第一个位置要特殊处理
if(i==1)
{
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data = e;
s->next = L;
L = s;
return true;
}
删除
按位删除ListDelete(L,i,e)
删除第i个位置的元素,并把值用e带回
- 找到第i-1个结点
- 判断p存不存在(即i合不合法,i位置结点存不存在)
- 定义一个指针q指向被删结点
- 把被删结点的值赋给e
- 把p的后驱指向q的后驱
- 释放q
bool LinkDelet(LinkList &L, int i, int e)
{
LNode *p = GetElem(L,i-1);
if(p==NULL) return false;
if(p->next==NULL) return false;
LNode *q = p->next;
e = q->data;
p->next = q->next;
free(p);
return true;
}
删除指定结点DeleteNode§
删除指定结点p
- 定义指针q指向p的后驱结点
- 把q的数据值赋给p
- p的后驱指向q的后驱
- 释放q
bool DeleteNode(LNode *p)
{
if(p==NULL) return flase;
LNode * q = p->next;
p->data = q->data;
p->next = q->next;
free(p);
return true;
}
注意:当p是最后结点时,不能用上述方法,只能从表头开始找p的前一个结点
建立
头插法
链表的逆置
LinkList List_HeadInsert(LinkList &L)
{
LNode *p; //p为要插入的元素
L = (LinkList)malloc(sizeof(LNode)); //创建头结点
L->next = NULL;
for(int i = 0;i<n;i++)
{
p = (LNode *)malloc (sizeof(LNode));
scanf("%d",&p->data);
p->next = L->next;
L->next = p;
}
return L;
}
尾插法
顺序存储,注意要有个结点始终指向尾结点
LinkList List_TailInsert(LinkList &L)
{
LNode *p,*r = L; //p为要插入的元素.r始终指向表尾元素
L = (LinkList)malloc(sizeof(LNode)); //创建头结点
L->next = NULL;
for(int i = 0;i<n;i++)
{
p = (LNode *)malloc (sizeof(LNode));
scanf("%d",&p->data);
p->next = r->next;
r->next = p;
r = p;
}
return L;
}
这篇博客详细介绍了单链表的定义、初始化、判空操作,包括不带头节点和带头节点两种情况。接着讨论了查找、插入和删除等基本操作,如按位查找、按值查找、后插、前插、按位插入和删除等。同时提到了建立单链表的头插法和尾插法。

2693

被折叠的 条评论
为什么被折叠?



