向单链表中插入新元素,并保证插入后,元素是有序的。
【程序实例】
1 struct ListNode 2 { 3 int val; 4 ListNode *next; 5 }; 6 7 bool sll_insert(ListNode **root, int value) 8 { 9 ListNode *PrevNode =NULL; 10 ListNode *Current = *root; 11 12 while (Current!=NULL && Current->val<value) 13 { 14 PrevNode=Current; 15 Current=Current->next; 16 } 17 18 ListNode *New = new ListNode; 19 if (New == NULL) 20 return false; 21 22 New->val=value; 23 24 New->next=Current; 25 26 if (PrevNode == NULL) 27 *root=New; 28 else 29 PrevNode->next=New; 30 31 return true; 32 }
===============================================================================
改进的方法:
分析:在上面的方法中,我们需要指定两个指针,一个指向当前结点,一个指向当前结点的前一个结点(注意,其初始化要为NULL,用于标记要插入的位置是否是在第一个结点的位置)。该方法需要区分对待两种情况:
(1)要插入的位置位于单链表的中部或者尾部,此时指向当前结点的前一个结点的指针的后面的位置即使要新插入的结点的位置,只需要将当前结点连接到新插入结点的后面,即可完成结点的插入:
1 PrevNode->next=New; 2 New->next=Current;
(2)当要插入结点的位置是一个结点,此时指向当前结点(即第一个结点)的前一个结点的指针PrevNode为NULL(因为它还没来得及在结点中赋值),此时只需要将新插入的结点的下一个结点设为当前结点,而将根节点设置为新插入的结点:
1 New->next=Current; 2 *root=New;
当原始的链表为空时的情况也包含在该情况中。
由于上面的代码需要分情况,下面对算法进行优化:
我们尝试使用一个指针完成任务,指向当前结点的指针是必不可少的,因为我们需要它访问结点中的val。我们在不断比较的过程中,最终当前结点的指针是指向要插入的结点后一个结点。
然而,当我们调整结点的形式,使得next域在结点的起始位置,指向该结点的指针的值是该结点的起始位置的地址,此时该地址也是next域的起始位置的指针。当我们要插入结点时,只需要将指向当前结点的next域的指针指向新插入的结点的next域的地址即可,而将新插入节点的next指向当前结点的指针即可。
【程序实例】
1 struct ListNode 2 { 3 ListNode *next; 4 int val; 5 }; 6 7 int sll_insert(ListNode **root, int value) 8 { 9 ListNode *Current=NULL; 10 11 while( (Current=*root)!=NULL && Current->val<value ) 12 { 13 root=&Current->next; 14 } 15 16 ListNode *New = new ListNode; 17 if(New ==NULL) 18 return -1; 19 New->val=value; 20 21 New->next=Current; 22 *root=New; //相对于对第一个大于value的位置进行重新赋值,将旧位置上的指针连接到新插入的结点的后面 23 24 return 0; 25 }
时间: 2024-10-15 11:50:05