小言_互联网的博客

数据结构——单链表的插入及删除

382人阅读  评论(0)

目录

 

一、按位序插入

二、指定结点的后插操作

三、指定结点的前插操作

四、按位序删除(带头结点)

五、指定结点的删除

六、总结


一、按位序插入

1.带头结点

LinkInsert(&L,i,e):插入操作,在表L中的第i个位置插入指定元素e。(找到第i-1个结点,将新结点插入其后)

注:头结点可以看作“第0个”结点


  
  1. typedef struct LNode{
  2. ElemType data;
  3. struct LNode *next;
  4. }LNode,*LinkList;
  5. //在第i个位置插入元素e(带头结点)
  6. bool ListInsert(LinkList &L,int i,ElemType e){
  7. if(i < 1)
  8. return false;
  9. LNode *p; //指针p指向当前扫描到的结点
  10. int j = 0; //当前p指向的是第几个结点
  11. p = L; //L指向头结点,头结点是第0个结点(不存数据)
  12. while(p != NULL && j < i - 1){ //循环找到第i-1个结点
  13. p = p->next;
  14. j++;
  15. }
  16. if(p == NULL) //i值不合法
  17. return false;
  18. LNode *s = (LNode *) malloc( sizeof(LNode));
  19. s->data = e;
  20. s->next = p->next;
  21. p->next = s; //将结点s连到p之后
  22. return false; //插入成功
  23. }

分四种情况讨论

① i = 1(将元素插在第一个位置),时间复杂度O(1)

1)j = 0,不执行while循环

2)p指向头结点

3)开辟一块新的结点空间s,将参数e存入到新结点s中

4)s指向结点的指针指向p所指向结点的指针

5)p指向结点的指针重新指向到新结点s

注:4)5)不能写反,原因是会造成后面的内容丢失,使s结点自己指向自己

②i = 3(将元素插在第三个位置),时间复杂度O(n)

1)执行while循环,j=2

2)p指向第i-1个结点,同3)4)5)

③插在表尾,时间复杂度O(n)

1)执行whle循环,j = i - 1

2)p指向最后一个结点,同3)4)5)

注:此时s指向结点的指针为NULL

④i > Length时

p指向的是NULL,插入失败

 

2.不带头结点


  
  1. bool ListInsert(LinkList &L,int i,ElemType e){
  2. if(i < 1)
  3. return false;
  4. if(i == 1){
  5. LNode *s = (LNode *) malloc( sizeof(LNode));
  6. s->data = e;
  7. s->next = L;
  8. L = s;
  9. return true;
  10. }
  11. LNode *p;
  12. int j = 1;
  13. p = L;
  14. while(p != NULL && j < i - 1){
  15. p = p->next;
  16. j++;
  17. }
  18. if(p == NULL)
  19. return false;
  20. LNode *s = (LNode *) malloc( sizeof(LNode));
  21. s->data = e;
  22. s->next = p->next;
  23. p->next = s;
  24. return false;
  25. }

分三种情况讨论

①i = 1

1)因为无头结点,所以要先开辟一块结点空间,将参数e存入到新结点s中

2)s指向结点的指针指向L,L指向s

注:如果不带头结点,则插入、删除第一个元素时,需要更改头指针L

②i > 1...

和带结点的操作一样

注:j初始为1,表示p刚开始指向的是第一个结点

 

二、指定结点的后插操作


  
  1. //后插操作:在p结点之后插入元素e
  2. bool InsertNextNode(LNode *p,ElemType e){
  3. if(p == NULL)
  4. return false;
  5. LNode *s = (LNode *) malloc( sizeof(LNode));
  6. if(s == NULL)
  7. return false;
  8. s->data = e;
  9. s->next = p->next;
  10. p->next = s;
  11. return true;
  12. }

思路:

1)先开辟一块结点空间

2)将参数存入到新结点中

3)s指向结点的指针指向p所指向结点的指针

4)p指向结点的指针重新指向到新结点s

 

三、指定结点的前插操作


  
  1. //前插操作:在p结点之前插入元素e
  2. bool InsertPriorNode(LNode *p,ElemType e){
  3. if(p == NULL)
  4. return false;
  5. LNode *s = (LNode *) malloc( sizeof(LNode))l
  6. if(s == NULL)
  7. return false;
  8. s->next = p->next;
  9. p->next = s;
  10. s->data = p->data;
  11. p->data = e;
  12. return true;
  13. }

由于不知道p的前驱结点信息,所以思路如下:

1)先开辟一块结点空间s

2)s指向结点的指针指向p所指向的指针

3)p所指向的指针指向s

4)复制p中元素到s

5)p中元素覆盖为e

 

 

四、按位序删除(带头结点)


  
  1. bool ListDelete(LinkList &L,int i,ElemType &e){
  2. if(i < 1)
  3. return false;
  4. LNode *p;
  5. int j = 0;
  6. p = L;
  7. while(p != NULL && j < i - 1){
  8. p = p->next;
  9. j++;
  10. }
  11. if(p == NULL)
  12. return false;
  13. if(p->next == NULL)
  14. return false;
  15. LNode *q = p->next; //令q指向被删除结点
  16. e = q->data; //用e返回元素的值
  17. p->next = q->next; //将*q结点从链中断开
  18. free(q); //释放结点的存储空间
  19. return true; //删除成功
  20. }

思路:

①头结点看作第0个结点

②新建指针q指向p所指向的指针

③将q指向的结点中元素赋值给e

④p结点的指针指向q所指向的指针

⑤释放q

 

五、指定结点的删除


  
  1. //删除指定结点p
  2. bool DeleteNode(LNode *p){
  3. if(p == NULL)
  4. return false;
  5. LNode *q = p->next; //令q指向*p的后继结点
  6. p->data = p->next->data; //和后继结点交换数据域
  7. p->next = q->next; //将*q结点从链中断开
  8. free(q); //释放后继结点的存储空间
  9. return true;
  10. }

 思路:

①先使q指向p的后继结点

②将q值赋给p

③p结点的指针指向q结点指向的指针(可能指向一个结点,也有可能是NULL)

④释放q

注:如果p是最后一个结点,只能寻找p的前驱

 

六、总结

 

 

 


转载:https://blog.csdn.net/qq_40310148/article/details/105713772
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场