数据结构-链表篇
来源:互联网 发布:ubuntu用u盘安装 编辑:程序博客网 时间:2024/06/06 07:06
数据结构 --链表
一直想把写过的数据结构给整理下来,很久没写了。先分享下写过的链表操作相关的比较有趣的题(代码都是可以运行的)。后续会补充
1. 经典问题,链表中环的问题,我有一篇博客专门解释环的问题,这里就不啰嗦了,也就是快慢指针的原理。直接上代码:
环的入口:
/*struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { }};*/class Solution {public: ListNode* EntryNodeOfLoop(ListNode* pHead) { ListNode* p1=pHead; ListNode* p2=pHead; // ListNode* p3=pHead; if(pHead==NULL||pHead->next==NULL) return NULL; do{ p1=p1->next; p2=p2->next->next; }while(p2!=NULL&&p2->next!=NULL&&p1!=p2); if(p1==p2) { p2=pHead; while(p2!=p1) { p2=p2->next; p1=p1->next; } return p1; } return NULL; }};
2.约瑟夫圈圈问题(m>n可以)
已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
通常解决这类问题时我们把编号从0~n-1,最后[1] 结果+1即为原问题的解。
/*struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { }};*/class Solution {public: ListNode* EntryNodeOfLoop(ListNode* pHead) { ListNode* p1=pHead; ListNode* p2=pHead; // ListNode* p3=pHead; if(pHead==NULL||pHead->next==NULL) return NULL; do{ p1=p1->next; p2=p2->next->next; }while(p2!=NULL&&p2->next!=NULL&&p1!=p2); if(p1==p2) { p2=pHead; while(p2!=p1) { p2=p2->next; p1=p1->next; } return p1; } return NULL; }};
3.合并两个排序的链表
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
/*struct ListNode { intval; structListNode *next; ListNode(intx) : val(x),next(NULL) { }};*/class Solution {public: ListNode* Merge(ListNode* pHead1, ListNode* pHead2) { if(pHead1==NULL) return pHead2; if(pHead2==NULL) return pHead1; ListNode* pHead=NULL; //保存新的头结点 ListNode* p1=pHead1; //为了写的方便,就将p1.p2替换原来的两个头结点 ListNode* p2=pHead2; ListNode* pre=pHead1; ListNode* pT=NULL; if(p2->val<=p1->val){ //确定头结点 pHead = p2; p2=p2->next; pHead->next=p1; pre = pHead; } else{ pHead =p1; p1=p1->next; pre =pHead; } //将2插入1中 while(p1!=NULL&&p2!=NULL){ if(p2->val<p1->val){ pT=p2; p2=p2->next; pre->next=pT; pT->next=p1; } else{ pre=p1; p1=p1->next; } } if(p1==NULL&&p2!=NULL){ pre->next = p2; p2=p2->next; } if(p2==NULL&&p1!=NULL) { pre->next = p1; p1=p1->next; } return pHead; }};
4. 从尾到头打印链表(面试题中经常会问的问题,写之前先问清楚是否可以改变链表的结构)
输入链表的表头,输出为需要打印的“新链表”的表头
/*** struct ListNode {* int val;* struct ListNode *next;* ListNode(int x) :* val(x), next(NULL) {* }* };*/修改链表结构:class Solution {public: vector<int> printListFromTailToHead(struct ListNode* head) { vector<int> list1; if(head == NULL){ return list1; } if(head->next==NULL) { list1.push_back(head->val); return list1; } ListNode* pri = head; ListNode* cur = head->next; pri->next = NULL; ListNode* q = NULL; while(cur->next!=NULL) { q = cur; cur =cur->next; q->next = pri; pri=q; } cur->next=pri; while(cur) { list1.push_back(cur->val); cur =cur->next; } return list1; }};利用栈(只不过内存消耗大,不推荐):class Solution {public: vector<int> printListFromTailToHead(struct ListNode* head) { vector<int> list1; if(head == NULL) return list1; stack<int> stack1; while(head) { stack1.push(head->val); head =head->next; } while(!stack1.empty()){ list1.push_back(stack1.top()); } return list1; }};只是逆序输出结点,不产生新表(递归): vector<int>printListFromTailToHead(struct ListNode* head) { vector<int> v; while(head != NULL) { v.insert(v.begin(),head->val); head = head->next; } return v; } class Solution {public: vector<int> list1; vector<int> printListFromTailToHead(struct ListNode* head) { if(head==NULL) return list1; list1=printListFromTailToHead(head->next); list1.push_back(head->val); return list1; }};
5.反转链表
输入一个链表,反转链表后,输出链表的所有元素
/*struct ListNode { intval; structListNode *next; ListNode(intx) : val(x),next(NULL) { }};*/class Solution {public: ListNode* ReverseList(ListNode* pHead) { if(pHead == NULL) return NULL; if(pHead->next==NULL) return pHead; ListNode* pri = pHead; ListNode* cur = pHead->next; pri->next = NULL; ListNode* q = NULL; while(cur->next!=NULL) { q = cur; cur =cur->next; q->next = pri; pri=q; } cur->next=pri; return cur; }}; //栈void print(listNode* head){ std::stack<listNode*>nodes ; listNode* pnode = head ; while(pnode!=NULL){ nodes.push(pnode); pnode = pnode->next;}while(!nodes.empty()){ listNode* p = nodes.top(); cout<<p->data<<endl; nodes.pop();} } //递归 void print(listNode* head){ if(head!= NULL){ if(head->next != null) { print(head->next);} printf("%d\t",head->data);}}
6.设有一个带表头结点的双向循环链表L,每个结点有4个数据成员:指向先驱结点的指针prior、指向后继结点的指针next、
存放数据的成员data和访问频度freq。所有结点的freq初始时都为0.每当在链表上进行一次L.Locate(x)操纵时,
令元素值x的结点的访问频度freq加1,并将该结点前移,
链接到现它的访问频度相等的结点后面,使得链表中所有结点保持按访问频度递减的顺序排列,以使频繁访问的结点总是靠近表头。
voidLocate(int &x) { <结点类型说明 > *p =first->next; while (p != first && p->data!=x ) p = p->next; if(p != first) { p->freq++ ; <结点类型说明 > *current = p; current->prior->next = current->next; current->next->prior =current->prior; p =current->prior; while (p != first && p->freq <current->freq ) p = p->prior; current->next = p->next ; current->prior = p; p->next->prior = current; p->next = current; } else printf(“Sorry. Not find!\n”); \*没找到*\ }
7.输入一个链表,输出该链表中倒数第k个结点。
/*struct ListNode { intval; structListNode *next; ListNode(intx) : val(x),next(NULL) { }};*/class Solution {public: ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) { if(pListHead==NULL||k==0) return NULL; ListNode* p_temp = pListHead; //一条用于从头遍历到k-1的位置 ListNode* q = pListHead; int i=0; while( i<k-1) { p_temp = p_temp->next; i++ ; if(p_temp == NULL) return NULL; } while(p_temp->next!=NULL){ p_temp = p_temp->next; q= q->next; } return q; }};
1 0
- 数据结构-链表篇
- 数据结构-链表篇
- Java数据结构(链表篇)
- 数据结构
- 数据结构
- 数据结构
- 数据结构
- 数据结构
- 数据结构
- 数据结构
- 数据结构
- 数据结构
- 数据结构
- 数据结构
- 数据结构
- 数据结构
- 数据结构
- 数据结构
- dijkstra+heap
- lamp的架构之haproxy
- vue.js 微信浏览器不支持lambda表达式
- vb.net 教程 1-8 日期时间类型1
- 敏捷开发之Scrum扫盲篇
- 数据结构-链表篇
- 计算机基础知识——操作系统(二):进程
- 子沐课堂——学员管理系统(前期准备+Model建立)
- linux重新编译内核
- CSS_5th_定位position
- multimap和multiset容器
- POJ 2463 Bungee Jumping G++
- 子沐课堂——Mysq从入门到精通(三)
- 链表部分翻转-Java