前面一篇博文簡要地講了下我在筆試準備過程中碰到過的有關字符串的題目,現在再提下有關鏈表的題目
(1) 具有鏈表頭的單鏈表
{
if(stu == NULL ||stu->next == NULL)
return stu;
p1=stu->next; //p1指向鏈表頭節點的下一個節點
p2=p1->next;
p1->next=NULL;
while(p2)
{
p3=p2->next;
p2->next = p1;
p1=p2;
p2=p3;
}
printf("p1 = %d,next = %dn ",p1->number,p1->next->number);
stu->next=p1; //將鏈表頭節點指向p1
return stu;
}
typedef struct student
{
int number;
char name[20];
int score;
struct student *next;
}student;
student *reverse2(student *stu)
{
student *p1,*p2,*p3;
if(stu == NULL ||stu->next == NULL)
return stu;
p1=stu; //p1指向鏈表的第一個節點
p2=p1->next;
while(p2)
p3=p2->next;
p2->next = p1;
p1=p2;
p2=p3; }
printf("p1 = %d,next = %d\n ",p1->number,p1->next->number);
stu=p1; //將鏈表第一個節點指向p1
return stu;
}
{
if(p == NULL || p->next == NULL)
{
head = p;
return p;
}
else
{
List* q = reverse(p->next, head);
q->next = p;
return p;
}
if(head==NULL || head->next==NULL)
return head;
node* tail= head->next;
node* newHead= reverse(head->next);
tail->next=head;
head->next=NULL;
return newHead;
}
比如有下面兩個鏈表:
鏈表2:2->4->6
遞歸方法的步驟如下:
(1)比較鏈表1和鏈表2的第一個節點數據,由於1<2,因此把結果鏈表頭節點指向鏈表1中的第一個節點,即數據1所在的節點。
(2)對剩餘的鏈表1(3->5)和鏈表2再調用本過程,比較得到結果鏈表的第二個節點,即2與3比較得到2。此時合併後的鏈表節點爲1->2。
接下來的過程類似(2),如此遞歸直到兩個鏈表的節點都被加到結果鏈表中
node * MergeRecursive(node *head1, node *head2)
{
node *head = NULL;
if (head1 == NULL)
{
return head2;
}
if (head2 == NULL)
{
return head1;
}
if ( head1->data < head2->data )
{
head = head1 ;
head->next = MergeRecursive(head1->next,head2);
}
else
{
head = head2 ;
head->next = MergeRecursive(head1,head2->next);
{
Node *res, *ret, *p, *q;
if(head1 == NULL) return head2;
ret = res = head1;
q = head2->next;
while(p && q)
{
if(p->value < q->value)
{
res->next = p;
res = p;
p = p->next;
}
else
{
res->next = q;
res = q;
q = q->next;
}
}
res->next = p ? p : q; //p或q有剩,把剩下的鏈表插入到結果鏈表後
return ret;
}
dnode *deletenode(dnode *head,dnode *node)
{
if(node->pre == NULL)
{
// 頭結點
head = head->next;
head->pre = NULL;
}
else if(node->next == NULL)
{
// 尾結點
node->pre->next = NULL;
}
else
{
// 中間結點
node->pre->next = node->next;
node->next->pre = node->pre;
}
free(node);
return head;
}
node *findMid(node *head) // 有鏈表頭
{
if(NULL == head)
return NULL;
node *fast, *slow;
fast = slow = head;
while((fast != NULL) && (fast->next != NULL))
{
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
node *findMid(node *head) // 無鏈表頭
{
if(NULL == head)
return NULL;
if(head->next == NULL || head->next->next == NULL)
return head;
node *fast = head;
node *slow = head;
while(fast->next != NULL && fast->next->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
設置兩個指針(fast, slow),初始值都指向頭,slow每次前進一步,fast每次前進二步,如果鏈表存在環,則fast必定先進入環,而slow後進入環,兩個指針必定 相遇。(當然,fast先行頭到尾部爲NULL,則爲無環鏈表)
當fast若與slow相遇時,slow肯定沒有走遍歷完鏈表,而fast已經在環內循環了n圈(1<=n)。假設slow走了s步,則 fast走了2s步(fast步數還等於s 加上在環上多轉的n圈),設環長爲r,則:
2s = s + nr
s= nr
設整個鏈表長L,入口環與相遇點距離爲x,起點到環入口點的距離爲a。
a + x = nr
a + x = (n – 1)r +r = (n-1)r + L - a
a = (n-1)r + (L – a – x)
{
if(NULL == head)
return NULL;
node *fast, *slow;
fast = slow = head;
while((fast != NULL) && (fast->next != NULL))
{
fast = fast->next->next; //走兩步
slow = slow->next; //走一步
if(fast == slow){ //有環
fast = head;
while(fast != slow){
fast = fast->next;
slow = slow->next;
}
return fast;
}
}
return NULL;
}
未完待續。。。