线性表-链表(索引)
- 单、循环链表
- 定义
- 初始化
- 不带头节点
- 带头节点
- 插入
- 建立单链表(头插入法)
- 建立单链表(尾插法)
- 按位序插入
- 指定节点(后插操作)
- 指定节点(前插操作)
- 查找
- 查找节点的值(按序号)
- 查找节点的值(按值)
- 删除
- 删除节点(按位序)
- 删除指定节点*p
- 汇总
1.1定义
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zdovwIx6-1601101792063)(…/BlogImages/带头VS不带头.png)]
typedef unsigned int ElemType;
typedef struct LNode {//定义单链表节点类型
ElemType data;// 数据域(每个节点存放一个数据元素)
struct LNode* next;//指针域(指向下一个节点)
}LNode, * LinkList;
2.1初始化(不带头节点)
//初始化一个空的单链表
bool InitLinkList(LinkList& L) {
L = NULL;
return true;
}
2.2初始化(带头节点)
//初始化一个带头节点单链表
bool InitList(LinkList& L) {
L = (LNode*)malloc(sizeof(LNode));//分配一个头节点
if (L == NULL)
return false;
L->next = NULL;
return true;
}
3.1建立单链表(尾插法)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cVTjVgfY-1601101792068)(…/BlogImages/尾插法.png)]
//尾插法通过尾指针r实现插入
LinkList List_TailInsert(LinkList& L) {
int x;
L = (LinkList)malloc(sizeof(LNode));//①初始化单链表并将L指针指向头节点
LNode* s, * r = L;//②将s和r指针都指向头节点
scanf("%d", &x);//③输入值
while (x!=99)
{
s = (LinkList)malloc(sizeof(LNode));//④将s指针指向新的节点
s->data = x;//⑤给新节点赋输入的值
r->next = s;//⑥上一节点的next指向新的节点(上一节点通过r指针能找到)
r = s;//⑦将r指针指向新的表尾节点(通过s即可找到新的指针的表尾节点)
scanf("%d", &x);
}
r->next = NULL;//⑧尾节点指针置空
return L;
}
3.2建立单链表(头插入法)
//头插法建立单链表
LinkList List_HeadInsert(LinkList &L) {
LNode* s; int x;
L = (LinkList)malloc(sizeof(LNode));//初始化单链表并将L指针,指向头节点
L->next = NULL;//初始为空链表
scanf("%d", &x);//输入节点值
while (x!=99)
{
s = (LNode*)malloc(sizeof(LNode));//将s指针指向新的节点
s->data = x; //为新的节点赋输入的值
s->next = L->next;//将上一节next指针赋值给新节点的next指针
L->next = s;//将上一节点的next指针指向s
scanf("%d", &x);
}
return L;
}
3.3按位序插入(不带头节点)
/// <summary>
/// 补充不带头节点的按照位序插入
/// </summary>
/// <param name="L"></param>
/// <param name="i"></param>
/// <param name="e"></param>
/// <returns></returns>
bool ListInserWithoutHead(LinkList &L,int i,ElemType e) {
if (i < 1)
return false;
if (i == 1) {//由于不带头节点插入第一个系欸但那需要特殊处理
LNode* s = (LNode*)malloc(sizeof(LNode));
s->data = e;
s->next = L;
L = s;
return true;
}
LNode* p = L;
int j = 1; //p 指向第L个节点
while (p!=NULL &&j<i-1)
{
p = p->next;
j++;
}//找前驱节点
if (p == NULL)
return false;
LNode* s = (LNode*)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
3.4指定节点(后插操作)
bool InsertNextNode(LNode* p, ElemType e) {
if (p == NULL)
return false;
LNode* s = (LNode*)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
3.5 指定节点(前插操作)
/// <summary>
/// 在指定节点前插操作(就是将指针域的值进行交换)
/// </summary>
/// <param name="p">节点</param>
/// <param name="e">待插入元素</param>
/// <returns></returns>
bool InsertBeforeNode(LNode *p,ElemType e) {
if (p == NULL)
return false;
LNode* s=(LNode*)malloc(sizeof(LNode));
if (s == NULL)
return false;//内存分配失败
s->next = p->next;
p->next = s;
s->data = p->data;//赋值交换下
p->data = e;
}
4.1查找节点的值(按序号),时间复杂度(O(n))
LNode* GetElem(LinkList L,int i) {
int j = 1;//计数,初始化为1
LNode* p = L->next;//头节点赋值给指针p
if (i == 0)
return L; //若i=0 返回头节点
if (i < 1)
return NULL; //若i无效 返回null
while (p&&j<i)
{
p = p->next;
j++;
}
return p;
}
4.2查找节点的值(按值),时间复杂度O(n)
LNode* LocateElem(LinkList L, ElemType e) {
LNode* p = L->next;
while (p!=NULL &&p->data!=e)
{
p = p->next;
}
return p;
}
5.1 删除节点(按位序)
/// <summary>
/// 按位序删除节点
/// </summary>
/// <param name="L"></param>
/// <param name="i"></param>
/// <returns></returns>
bool DelNode(LinkList &L,int i) {
if (i<1)
return false;
//按位序查找前驱节点
LNode* p;
int j = 0;//指向的是第几个节点 头节点为0
p = L;
while (p!=NULL&&j<i-1)
{
p = p->next;
j++;
}
//或者LNode* p = GetElem(L, i - 1);
if (p == NULL||p->next==NULL) //i值不合法或p后面没有节点了
return false;
LNode* q = p->next;//要删除的节点
p->next = q->next; //p指向删除的下一节点
free(q);
return true;
}
5.2删除指定节点*p
/// <summary>
/// 删除*p
/// </summary>
/// <param name="p"></param>
/// <returns></returns>
bool DelBeforeNode(LNode *p) {
if (p == NULL)
return false;
LNode* q = p->next;
p->data = q->next->data;//把*p的后继节点*q的值赋值到前驱节点*p ,再移除q 与前插操作思想一致
p->next = q->next;
free(q);
return true;
}