对于顺序表而言,每次在表尾处后插入和删除的速度最快,每次在表头处做插入和删除时,需要移动大量的数据元素,删除和插入操作最慢。而对于单链表刚好相反。因为单链表是顺序存取,挨个遍历;而顺序表可以随机存取
6-5 带头结点的单链表就地逆置 (5 分)(就地:利用原节点,不生成新节点)
本题要求实现一个函数,对带有头结点的单链表进行就地逆置。
把每个元素结点从原链上取下,插在头结点(L->next)的后面。(相当于把所有的元素结点插在空表里)
1.首先让头结点的指针域为NULL,p指向a1。把结点a1(即p所指向的结点)插在头结点之后。
(单链表插入结点的操作:先修改插入结点的指针域,p->next=L->next ;再修改前驱结点的指针域L->next=p; ) 2.p按照原链下移,重复此操作
void reverse ( LinkList L ) { LinkList p=L->next;//p指向首元结点 LinkList q; L->next=NULL;//首先将头结点的指针域置为NULL,这句容易忘。否则会运行超时(结点的指针域没有为空指针的了),因为之后我们会把这个链表进行输出,会输出一片0000乱码,运行超时 while(p)//条件是p不为空,即所有结点都参与循环,遍历链表 { q=p->next;//q暂存一下p的后继,把原先还没修改的p->next送给q p->next=L->next;//把p所指向的结点插入到L结点的后面,修改p的指针域 L->next=p;//修改L的指针域 p=q;//p按照原链下移 } }
if(!L) return 0;//如果链表是空表,直接return即可 //如果链表不空,让p指向第二个结点,把首元结点的指针域置为空。 //L是头指针,指向首元结点,第二个结点的地址为L->next p=L->next;L->next=NULL; while(p) { q=p->next; //把p所指向结点插入到L所只想结点之前,先修改插入结点的指针域 p->next=L;L=p;//**************** p=q; }
不带头结点的单链表,因为头指针L不断变化,形参必须使用引用参数
此时q所指向的结点就会被删掉(修改p的后继,释放q),
此时p,q的所指向结点的数据域不相等,因为该表是有序表,故后面没有1了,p下移
void delsame(LinkList L) { p=L->next;//让p指向第一个结点 if(!P) return 0; while(p->next)//判断p是否有后继,即p->next不为空 { q=p->next;//q为p的后继 if(p->data==q->data)//删除q,先修改p的指针域 { p->next=q->next;free(q); } else p=p->next;//p下移 } }
顺序表的删除,不是删除一个节点就向前移,而是*******
因为k,i所指向结点的数据域相同,所以不把i放在此处,i下移。做完之后,返回k+1
void del(SqList &L)//是引用参数,修改了这个顺序表 { k=0;//顺序表,k初始化为下标为0的元素 for(int i=1;i<L.length;i++) {//作比较 if(L.elem[k]!=L.elem[i]) { L.elem[k+1]=L.elem[i]; k++; } } if(L.length==0) return 0;//L.length==0,顺序表是空表,没有做删除 if(L.length>0) L.length=k+1; }
1.插入40的话,就要找40的插入位置,p初始化指向首元结点,q是p的前驱,所以q初始化为指向头结点
2.除了一般情况外,在考虑时,还要考虑链表的两个端点。遍历至p为空后
3.在最前面做插入的话