对链表某个节点的操作除第一个节点外,都需要找到该节点的前驱节点,这是关键。
1.不带头结点单链表:
①定义
typedef char ListData;
typedef struct node
{
ListData data;
struct node * link;
}ListNode;
typedef ListNode * LinkList;
LinkList first; //定义头指针
LinkList last; //定义尾指针
②插入:没有头结点插入有三种情况
(1)在第一个节点前插入
(2)在链表中间插入
(3)在链表末尾插入
/* 参数列表:
** LinkList & first:进行操作的链表头指针,
** x:插入的数据,
** i:插入的位置
*/
void Insert(LinkList & first,int x,int i)
{
ListNode * p = first ; //用指针p接收插入节点的上一个节点
int k = 0;
while(p!=NULL&&k<i-1) //p节点不为空节点并且还为找到i的位置
{
p = p->link; //遍历链表,找到第i-1个节点,用p指针接收
k++;
}
if(p==NULL&&first!=NULL) //不是空链表且遍历完链表没有找到第i-1个节点
{
printf("无效的插入位置\n");
return 0;
}
//找到了第i-1个节点
//创建新节点 malloc返回值类型为(void *)强制转换为(LinkNode *)类型
ListNode * newNode = (ListNode *)malloc(sizeof(ListNode));
newNode->data = x; //添加数据
if(first==NULL||i=0) //如果是空链表或者插入位置为头指针后
{
//新节点指针域指向头指针指向的节点(也就是第一个节点),或者空链表NULL,新节点也成为第一个节点。
newNode->link = first;
//如果为空链表,则新节点也是尾节点
if(first==NULL) last = newNode;
//头指针指向新的第一个节点
first = newNode;
}else{ //在中间或者末尾插入
//新节点的指针域指向p节点的下一个节点
newNode->link = p->link;
//如果p是最后一个节点,尾指针指向新节点
if(p->link==NULL) last = newNode;
//p的指针域指向新节点
p->link = newNode;
}
return 1;
}
③删除
/* 参数链表
** first:链表头指针
** i:要删除的节点
*/
int Delete(LinkList & first,int i)
{
ListNode *p,*q; //用q指针指向删除的节点,以便释放
if(i==0) //删除第一个结点
{
q = first; //first指向的节点,即第一个节点
first = first->link; //将first指向原节点的下一个节点
}else{
p = first;
int k = 0;
while(p!==NULL&&k<i-1)
{
p = p->link;
k++; //遍历链表,直到p为空或是找到第i-1个节点
}
if(p==NULL||p->link==NULL) //没找到第i-1个节点但是链表结束了
{
printf("无效的删除位置\n");
return 0;
}else{
q = p->link;
p->link= q->link;
}
if(q==last){ //如果p->link节点是尾节点
last = p; //尾指针指向p指针指向的节点
}
k = q->data; //用k接收删除节点的数据域
free(q); //释放q指针指向的内存空间
return k; //返回删除的数据
}
}
2.带头结点的单链表
①插入
/* 参数列表
** first:链表头指针
** x:插入节点数据域
** i:插入的位置
*/
int Insert(LinkList first,ListData x,int i)
{
ListNode * p;
int k = 0;
while(p!=NULL&&k< i-1)
{
p = p->link;
k++;
}
if(p==NULL){
printf("无效的插入位置\n");
return 0;
}
ListNode * newNode = (ListNode *)malloc(sizeof(ListNode));
newNode->data = x;
newNode->link = p->link; //新节点指针域指向p的后继
p->link = newNode; //p的后继为插入的节点
return 1;
}
②删除
int Delete(ListLink first,int i)
{
ListNode * p ,*q;
int k = 0;
while(p!=NULL&&k< i-1)
{
p = p->link;
k++;
}
if(p==NULL||p->link==NULL){
printf("无效的删除节点\n");
return 0;
}
q = p->link; //找到第i-1个节点,将指针p指向该节点的后继
p->link = q->link; //将第i-1个节点的指针域指向原本后继的后继
free(q);
return 1;
}