本来准备自己写一个单链表的排序,但是没写出来,原因是不知道怎么判断最外层的循环结束条件。只好参考网上的例子了,参考链接:http://blog.csdn.net/wzy_1988/article/details/8129505,另外我感觉以下两种法案不是最优解
1.当然如果是先求链表长度 n=length(head);,这样的for(i=0;i<n;i++)外部循环,感觉就没啥意思了
2.还有就是一种只交换链表中两个结点的data值,而不是交换两个结点,对于这种,我感觉如果只有一个成员变量data还行,如果这个结构体里面的成员变量有若干个,这样能行吗?
下面的代码是正解,其实这个循环退出条件就是每次冒泡排完一个数之后,就让tail指针指向有序结点,比如6 5 4 3 2 1,那么指向的顺序是6,5,4,3,2
struct LinkList * bubbleSort(struct LinkList *head){
if(head==NULL||head->next==NULL) return NULL;
struct LinkList *tmp=head,*tail=NULL;
struct LinkList *p,*q;
while(head->next->next!=tail){
for(p=head;p->next->next!=tail;p=p->next){
if(p->next->data>p->next->next->data){
q=p->next;
p->next=q->next;
q->next=p->next->next;
p->next->next=q;
}
}
tail=p->next;
}
return head;
}
当然单链表还有很多很有意思的题,参考链接:http://kofsky.iteye.com/blog/283250
1.怎么判断链表中是否有环?
2.给你一个单向循环链表,怎么找出这个链表循环部分的第一个节点?
3.链表逆序?
4.一个单向链表,不知道头节点,一个指针指向其中的一个节点,问如何删除这个指针指向的节点?
5.给定一个链表的头指针,在一次遍历中,找出这个链表中的中间节点并返回。
6.查找链表中倒数第k个节点(只允许遍历链表一次)
7.编写实现链表排序的一种算法
8.找两个链表的第一个公共节点
其中1,3,5,7都已实现,在以后我会陆续实现6中的归并两个链表排序,7,8等算法
2.给你一个单向循环链表,怎么找出这个链表循环部分的第一个节点?
跟第一个略有不同。第一个只是判断是否有环,而这个是要找出第一个节点。
标记法不错。hash也可以,貌似
4.一个单向链表,不知道头节点,一个指针指向其中的一个节点,问如何删除这个指针指向的节点?
把next节点的key区域复制到本节点,然后删除next节点
6.查找链表中倒数第k个节点
两个指针,保持距离k
8.找两个链表的第一个公共节点
如果有公共节点,那么该节点后面的节点全部都是两链表公共部分。
以下实现代码参考链接:http://www.cppblog.com/koson/archive/2010/04/21/113142.aspx
下面的代码都是直接copy的,但是看一眼就明白了,感觉思路知道了,代码应该没啥问题
找到链表的中间结点(感觉这个思路很巧妙,代码非常简单,其实找到链表的中间节点,判断链表是否有环,找到链表的倒数第k各结点的都是思路难,而代码易,且这三道题的思路类似,都是用两个指针,巧妙的运用这两个指针的"距离"来解题)
LinkList* findMiddle(LinkList* head){
ListNode *p1, *p2;
if (head == NULL || head->next == NULL) {
return head;
}
p1 = p2 = head;
while (1){
if (p2->next != NULL && p2->next->next != NULL){
p2 = p2->next->next;
p1 = p1->next;
}
else {
break;
}
}
return p1;
}
判断链表是否有环
int isLoop(LinkList *head){
ListNode *p1, *p2;
p1 = p2 = head;
if (head == NULL || head->next == NULL){
return 0;
}
while (p2->next != NULL && p2->next->next != NULL){
p1 = p1->next;
p2 = p2->next->next;
if (p1 == p2){
return 1;
}
}
return 0;
}
未完待续:下一节 链表算法三之静态链表