题:两个链表,一升一降。合并为一个升序链表。
分析:(假设升序的链表为链表1,降序的链表为链表2,p1,p2分别作为它们的迭代器,还有一个合并链表用于存放合并后的数据)
法一、最容易想到的且容易实现的就是使两个表都变成升序,然后就是经典的合并排序算法的步骤了,步骤是构建p1,p2两个迭代器,分别用于迭代两个链表,每次遍历,若p1所指的节点数据大于p2所指的节点数据则将p1所指的节点数据插入到要合并链表中去且使p1指向下一个节点,否则将p2将所指的节点数据插入到合并链表中去且使p2指向下一个节点,直到p1和p2任意一个指向了NULL为止。最后可能两个链表中尚有剩余的节点,将其逐个插入到合并链表中去即可。
法二、使用递归方法后序遍历降序链表2,遍历顺序就相当于升序的顺序了。在递归遍历链表2的过程中,需要处理有以下三件事:(注意顺序)
(1) 如果p2的数据小于p1的就插入到合并链表中
(2) 如果p2的数据大于p1,那么就对链表1循环遍历,每次将p1中的数据插到合并链表中,直到p2不大于p1,且p1不为空
(3) 如果p1为空,就直接将p2插入到合并链表中
(这个方法你想到了没!)
- /**
- Author:花心龟
- Blog:http://blog.youkuaiyun.com/zhanxinhang
- **/
- #include <stdio.h>
- #include <malloc.h>
- #include <stdlib.h>
- typedef struct list_node
- {
- int data;
- struct list_node * next;
- }list_node;
- list_node *list1=NULL; //链表头结点
- list_node *list2=NULL; //链表头结点
- void list_print(const list_node *p)//打印该链表函数
- {
- if(p==NULL)return;
- while(p!=NULL)
- {
- printf("%d ",p->data);
- p=p->next;
- }
- printf("\n");
- }
- void list_create(list_node* &head, int data[], int N)
- {
- if(data == NULL) return;
- int i;
- list_node *p;
- p = (list_node*)malloc(sizeof(list_node));
- p->data = data[0];
- p->next = NULL;
- head = p;
- for(i=1;i<N; i++)
- {
- p->next = (list_node*)malloc(sizeof(list_node));
- p->next->data = data[i];
- p->next->next = NULL;
- p=p->next;
- }
- }
- void list_reverse(list_node* &head) //使链表反序
- {
- if(head == NULL) return ;//如果head1为空,则返回
- list_node *p,*q;
- q=head;
- p=head->next;
- while(p!=NULL)
- {
- head->next=p->next; //将头指针的next指向p的下一个节点
- p->next=q; //将p的next值反指向它的前一个节点q
- q=p; //q移向p的位置
- p=head->next; //p移向它的下一个位置
- }
- head = q;
- }
- void list_destroy(list_node *head) //销毁函数
- {
- list_node *pmove=NULL,*pdel=NULL;
- pmove=head;
- while(pmove!=head)
- {
- pdel=pmove;
- free(pdel);
- pmove=pmove->next;
- }
- }
- list_node* merge_two_list() //合并链表1和链表2(法一)
- {
- list_reverse(list2); //反转链表使之与链表一样升序排列
- list_node *list_merged; //和并后的链表
- list_node *p1,*p2,*p0;
- list_merged = (list_node*)malloc(sizeof(list_node));
- list_merged->data = 0;
- list_merged->next = NULL;
- p0 = list_merged;
- p1=list1;
- p2=list2;
- while(p1!=NULL && p2!=NULL)
- {
- if(p1->data < p2->data)
- {
- p0->next=(list_node*)malloc(sizeof(list_node));
- p0->next->data=p1->data;
- p0->next->next=NULL;
- p0=p0->next;
- p1=p1->next;
- }
- else
- {
- p0->next=(list_node*)malloc(sizeof(list_node));
- p0->next->data=p2->data;
- p0->next->next=NULL;
- p0=p0->next;
- p2=p2->next;
- }
- }
- while(p1!=NULL)
- {
- p0->next=(list_node*)malloc(sizeof(list_node));
- p0->next->data=p1->data;
- p0->next->next=NULL;
- p0=p0->next;
- p1=p1->next;
- }
- while(p2!=NULL)
- {
- p0->next=(list_node*)malloc(sizeof(list_node));
- p0->next->data=p2->data;
- p0->next->next=NULL;
- p0=p0->next;
- p2=p2->next;
- }
- return list_merged;
- }
- list_node* p0=(list_node*)malloc(sizeof(list_node));
- list_node* phead=p0;
- list_node* &p1=list1; //p1与list1绑定
- list_node* foreach(list_node* p2) //递归合并(法二)
- {
- if(p2==NULL) return phead;
- foreach(p2->next);
- if(p1->data > p2->data)
- {
- p0->next = (list_node*)malloc(sizeof(list_node));
- p0->next->data = p2->data;
- p0->next->next = NULL;
- p0=p0->next;
- return phead;
- }
- while(p1!=NULL && p1->data<=p2->data)
- {
- p0->next = (list_node*)malloc(sizeof(list_node));
- p0->next->data = p1->data;
- p0->next->next = NULL;
- p0=p0->next;
- p1 = p1->next;
- }
- if(p1==NULL)
- {
- p0->next = (list_node*)malloc(sizeof(list_node));
- p0->next->data = p2->data;
- p0->next->next = NULL;
- p0=p0->next;
- }
- return phead;
- }
- //Blog:http://blog.youkuaiyun.com/zhanxinhang
- int main()
- {
- int list1_data[] = {1,4,6,8,10}; //链表数据升序 可在这里该数据进行测试
- int list2_data[] = {14,9,3,2}; //链表数据降序
- list_create(list1,list1_data,5); //构建单链表
- list_create(list2,list2_data,4); //构建单链表
- list_print(list1);
- list_print(list2);
- //list_node *list_merged=merge_two_list(); //合并两个链表
- //list_print(list_merged->next); //打印合并后的链表
- list_node *list_merged2=foreach(list2); //使用递归合并两个链表
- list_print(list_merged2->next);
- list_destroy(list1); //销毁链表
- list_destroy(list2); //销毁链表
- // list_destroy(list_merged); //销毁合并后的链表
- list_destroy(list_merged2); //销毁合并后的链表
- system("pause");
- return 0;
- }
题:如何删除链表的倒数第m的元素?
分析:构建p0,p1两个迭代器,初始使p0和p1指向头结点,接着使p1移动到第m+1项,然后指向头得p0与p1同时前进,当p1指向空节点的时候结束,这时p0所指的位置就是倒数第m个,时间复杂度为O(n)
实现代码:(为了学习的需要,现在C++朋友采用c++实现,不能满足c朋友要采用c实现的愿望,此实为c++朋友的遗憾,不过一切重在思想。^_^)
- /**
- Author:花心龟
- Blog:http://blog.youkuaiyun.com/zhanxinhang
- **/
- #include <iostream>
- #include <list>
- using namespace std;
- class App
- {
- list<int> *plist;
- void delete_node_at_last(int m) //today`s topic
- {
- list<int>::iterator p0, p1;
- p0=p1=p2=plist->begin();
- //使p1移到第m+1项
- for(int i=1; i<=m; i++)
- p1++;
- //p0和p1同时前进,当p1到达终点时p0所指向的就是倒数第m个节点
- while(p1!=plist->end())
- p0++,p1++;
- //删除节点
- plist->erase(p0);
- }
- void create_list()
- {
- int list_data[]={1,2,3,4,5,6,7,8,9}; //链表数据
- plist = new list<int>(list_data, list_data+sizeof(list_data)/sizeof(int));
- }
- void print_list()
- {
- list<int>::iterator it;
- for(it=plist->begin(); it!=plist->end(); it++)
- cout<<*it<<' ';
- }
- public:
- //test in run funtion
- void run()
- {
- create_list();
- delete_node_at_last(3); //删除倒数第三个节点
- print_list();
- }
- ~App()
- {
- delete plist;
- }
- };
- //Blog:http://blog.youkuaiyun.com/zhanxinhang
- int main()
- {
- App myapp;
- myapp.run();
- system("pause");
- return 0;
- }
1万+

被折叠的 条评论
为什么被折叠?



