数据结构学习:单链表的基本操作
单链表的基本操作
单链表的基本操作之插入
ListInsert(&L,i,e):插入操作。在表L中的第i个位置上插入指定元素e。
即将插入位置的前一个节点的指针指向插入节点,插入节点的指针指向原来第i个位置的节点
插入前:
插入后:
//在带头结点的链表的第i个位置插入元素e
bool ListInsert(LinkList &L,int i, ElemType e)
{
if(i<1)
return false;
LNode *p; //定义一个指针p
int j = 0; //用来标注指针p指向的第几个结点
p = L; //L指向头指针,头指针是第0个结点,将p指向头指针
while(p != NULL && j<i-1) //通过循环来找到第i-1个结点
{
p = p->next;
j++;
}
if(p == NULL) //i值不合法
return false;
//此时的p指向的是要插入位置的前一个结点
LNode *s = (LNode *)malloc(sizeof(LNode));//定义一个结点s用来插入;
s->data = e; //将e赋值给结点s的数据域
s->next = p->next; //将要插入位置的下一个结点的地址赋给s结点的指针域
p->next = s; //插入位置的前一个结点的指针域指向插入的结点
return true; //插入成功
//可以直接调用后插方法,两种方法效果一样
//InsertNextNode(p,e);
}
//后插操作:在结点p之后插入元素e
bool InsertNextNode(LNode *p,ElemType e)
{
if(p == NULL) //p值不合法
return false;
//此时的p指向的是要插入位置的前一个结点
LNode *s = (LNode *)malloc(sizeof(LNode));//定义一个结点s用来插入;
if(s == NULL) //内存分配失败
return false;
s->data = e; //将e赋值给结点s的数据域
s->next = p->next; //将要插入位置的下一个结点的地址赋给s结点的指针域
p->next = s; //插入位置的前一个结点的指针域指向插入的结点
return true; //插入成功
}
//在不带头结点的链表的第i个位置插入元素e
bool ListInsert(LinkList &L,int i, ElemType e)
{
if(i<1)
return false;
if(i == 1)//如果要插入的位置为第一个结点
{
LNode *s = (LNode *)malloc(sizeof(LNode));//定义一个结点s用来插入;
s->data = e; //将要插入的值e赋值给结点s的数据域
s->next = L; //将头指针L指向的地址赋给s结点的指针域
L = s; //头指针L指向s结点
return true;
}
LNode *p; //定义一个指针p
int j = 1; //用来标注指针p指向的第几个结点
p = L; //p指向第一个结点
while(p != NULL && j<i-1) //通过循环来找到第i-1个结点
{
p = p->next;
j++;
}
if(p == NULL) //i值不合法
return false;
//此时的p指向的是要插入位置的前一个结点
LNode *s = (LNode *)malloc(sizeof(LNode));//定义一个结点s用来插入;
s->data = e; //将e赋值给结点s的数据域
s->next = p->next; //将要插入位置的下一个结点的地址赋给s结点的指针域
p->next = s; //插入位置的前一个结点的指针域指向插入的结点
return true; //插入成功
}
带不带头指针的链表的后插操作是一样的
前插操作可以看做后插操作后交换两结点的数据域的值
//在结点p前插一个值为e
bool InsertPriorNode(LNode *p,ElemType e)
{
if(p == NULL) //p值不合法
return false;
LNode *s = (LNode *)malloc(sizeof(LNode));//定义一个结点s用来插入;
if(s == NULL) //内存分配失败
return false;
//实现后插
s->next = p->next; //将要插入位置的下一个结点的地址赋给s结点的指针域
p->next = s; //插入位置的结点的指针域指向插入的结点
//后插后交换数据等同于前插
s->data = p->data; //将p结点赋值给结点s的数据域
p->data = e; //将e的值赋给p结点
return true; //插入成功
}
//在结点p前插一个结点s
bool InsertPriorNode(LNode *p,LNode *s)
{
if(p == NULL || s == NULL) //p结点与s结点不合法
return false;
//实现后插
s->next = p->next; //将要插入位置的下一个结点的地址赋给s结点的指针域
p->next = s; //插入位置的结点的指针域指向插入的结点
//后插后交换数据等同于前插
ElemType temp = s->date
s->data = p->data; //将p结点赋值给结点s的数据域
p->data = temp; //将s结点的值赋给p结点
return true; //插入成功
}
单链表的基本操作之删除
ListDelete(&L,i,&e):删除操作。删除表L中第i个位置的元素,并用e返回删除元素的值。
原理:
找到第 i-1 个结点,将其指针指向第i+1个结点,并释放第i个结点
//删除操作
bool ListDetele(LinkList &L,int i,ElemType &e)
//在链表L中删除第i个结点,并将其值返回为e
{
if(i<1)
return false;
LNode *p; //定义一个指针p
int j = 0; //用来标注指针p指向的第几个结点
p = L; //L指向头指针,头指针是第0个结点,将p指向头指针
while(p != NULL && j<i-1) //通过循环来找到第i-1个结点
{
p = p->next;
j++;
}
if(p == NULL) //p值不合法
return false;
if(p->next == false)//p结点后面没有结点
return false;
LNode *q = p->next; //定义一个指针q来指向要删除的结点
e = q->data; //用e来存储要删除的数据
p->next = q->next; //p指针指向要删除的结点的下一位,将q从链表中断开
free(q); //释放结点q
return true;
}
//删除指定结点
//p结点的数据域与p结点的下一个结点交换
//p结点的指针域指向下下一个结点,并将p结点的下一个结点删除
原理:将P结点与其下一个结点进行交换,然后删除p结点的下一个结点
bool DeteleNode(LNode *p)
{
if(p == NULL) //p值不合法
return false;
LNode *q = p->next; //定义一个指针q来指向要删除的结点
p->data = p->next->data; //p指针指向要删除的结点的下一位,将q从链表中断开
p->next = q->next;
free(q); //释放结点q
return true;
}
但是这种方法存在局限性,如果要删除的结点是最后一个结点的话,不能使用该方法,只能从头结点进行查找,然后删除.