单链表中的常见算法问题(剑指offer5/13/15/16/17)
来源:互联网 发布:js对象和字符串区别 编辑:程序博客网 时间:2024/06/16 10:44
1.单链表的结点
struct ListNode {int m_nKey;ListNode* m_pNext;};
2.创建链表
ListNode* createList(int length) {//创建表头结点ListNode* head = new ListNode();head->m_pNext = NULL;ListNode* p = head;int value = 0; //临时存储用户键入的第i个结点值for (int i = 0; i < length; ++i) {cout << "ListNode" << i << ":\t";cin >> value;//将新创建的结点插入链表中ListNode* q = new ListNode();q->m_nKey = value;q->m_pNext = NULL;p->m_pNext = q;p = q;}return head;}
3.删除链表
void deleteList(ListNode* head) {if (NULL == head) {return;}ListNode* p = head;ListNode* q = p;while (p->m_pNext) {q = p;p = p->m_pNext;delete q;q = NULL;}delete head;head = NULL;}
4.遍历输出链表(从表头到表尾)
void showList(ListNode* head) {//如果是空链表直接退出if (NULL == head)return;ListNode* p = head->m_pNext;while (p != NULL) {cout << p->m_nKey << "\t";p = p->m_pNext;}cout << endl;}
5.链表的长度
int listLength(ListNode* head) {if (NULL == head) {return 0;}int length = 0;ListNode*p = head->m_pNext;while (NULL != p) {p = p->m_pNext;++length;}return length;}
6.链表逆置
ListNode* listReverse(ListNode* sourceHead) {if (NULL == sourceHead)return NULL;ListNode* newHead = new ListNode();newHead->m_pNext = NULL;ListNode* p = NULL; //中间结点while (sourceHead->m_pNext != NULL) {//将原来链表的第一个结点从链表中删除p = sourceHead->m_pNext;sourceHead->m_pNext = p->m_pNext;//将删除掉的结点以头插法插入到新的链表中p->m_pNext = newHead->m_pNext;newHead->m_pNext = p;}return newHead;}
7.O(1)时间删除一个指定结点
void deleteListNode(ListNode* pHeadListNode, ListNode* pToBeDeleted) {if (NULL == pHeadListNode || NULL == pToBeDeleted) {return;}//方法二:在保证链表中包含待删除结点的前提下,将待删除结点的下一个结点值//替换掉要删除结点的值,然后删除待删除结点的下一个结点//如果待删除结点是链表中的唯一结点ListNode* pHeadNext = pHeadListNode->m_pNext;if (pHeadNext == pToBeDeleted && pHeadNext ==NULL) {delete pToBeDeleted;pToBeDeleted = NULL;pHeadNext = NULL;}//如果要删除的结点不是最后一个结点,且待删除的链表的长度大于1else if (pToBeDeleted->m_pNext != NULL) {ListNode* pDeletedNext = pToBeDeleted->m_pNext;pToBeDeleted->m_nKey = pDeletedNext->m_nKey;pToBeDeleted = pDeletedNext->m_pNext;delete pDeletedNext;}//如果待删除结点是链表的末尾结点(也是最常见的操作方法)else {//方法一:找到要删除结点,用其前一个结点指向其下一个结点,从而达到删除的目的ListNode* p = pHeadListNode;ListNode* q = pHeadListNode->m_pNext;while (q != pToBeDeleted && q != NULL) {p = q;q = q->m_pNext;}if (q != NULL) {p->m_pNext = q->m_pNext;}}}
8.输出单链表中的倒数第K个结点的值
int findLastKNodeValue(ListNode* head, const unsigned int k) {if (NULL == head || k <= 0) {return -1;}//计数器unsigned int count = 0;ListNode* p = head;ListNode* q = head;//如果链表长度多于k,则q先遍历k个值while (count < k && q != NULL) {q = q->m_pNext;++count;}//如果少于k直接退出if (NULL == q) {return -1;}//如果链表的结点多于k个,两个指针一起遍历到先遍历指针为NULL时while (NULL != q) {q = q->m_pNext;p = p->m_pNext;}//当链表长度多于k时,输出倒数第k个结点的值return p->m_nKey;}
9.合并两个排序的链表
ListNode* mergeSortedLinkedList(ListNode* head1, ListNode* head2) {//有个链表为空时返回另外一个链表即可--代码的鲁棒性if (NULL == head1) {return head2;}if (NULL == head2) {return head1;}//合并后的新头 结点ListNode* head = new ListNode();head->m_pNext = NULL;ListNode* s = head;while (NULL != head1->m_pNext && NULL != head2->m_pNext) {ListNode* p = head1->m_pNext;ListNode* q = head2->m_pNext;if (p->m_nKey < q->m_nKey) {head1->m_pNext = p->m_pNext;p->m_pNext = s->m_pNext;s->m_pNext = p;s = p;} else {head2->m_pNext = q->m_pNext;q->m_pNext = s->m_pNext;s->m_pNext = q;s = q;}}while (NULL != head1->m_pNext) {ListNode* p = head1->m_pNext;head1->m_pNext = p->m_pNext;p->m_pNext = s->m_pNext;s->m_pNext = p;s = p;}while (NULL != head2->m_pNext) {ListNode* q = head2->m_pNext;head2->m_pNext = q->m_pNext;q->m_pNext = s->m_pNext;s->m_pNext = q;s = q;}return head;}
测试代码
/* * * Created on: 2014-3-20 16:16:52 * Author: danDingCongRong */#include<iostream>using namespace std;int main() {int listLen = 0;cout << "输入链表的长度:\t";cin >> listLen;ListNode* head = createList(listLen);cout << "原始链表:" << endl;showList(head);cout << "链表的长度为:" << listLength(head) << endl;ListNode* newHead = listReverse(head);cout << "逆置后的链表:" << endl;cout << "" << endl;showList(newHead);cout << "倒数第5个数是:" << endl;cout << findLastKNodeValue(newHead, 5) << endl;ListNode* head1 = createList(listLen);cout << "原始链表:" << endl;showList(head1);ListNode* head2 = createList(listLen);cout << "原始链表:" << endl;showList(head2);cout << "合并两个有序的链表:" << endl;ListNode* head3 = mergeSortedLinkedList(head1, head2);showList(head3);cout << "链表的长度为:" << listLength(head3) << endl;return 0;}
注:部分代码参考自剑指offer
0 0
- 单链表中的常见算法问题(剑指offer5/13/15/16/17)
- 前端面试中的常见的算法问题
- 前端面试中的常见的算法问题
- 前端面试中的常见的算法问题
- 前端面试中的常见的算法问题
- 前端面试中的常见的算法问题
- 前端面试中的常见的算法问题
- 前端面试中的常见的算法问题
- 前端面试中的常见的算法问题
- 剑指offer5 利用两个栈模拟队列
- 剑指offer5:从头到尾打印链表
- 前端js面试中的常见的算法问题
- 前端面试中的最常见的算法问题
- Java中的常见算法
- MapReduce中的常见算法
- 剑指offer5,从尾到头打印链表
- 剑指offer5——从尾到头打印链表
- 剑指Offer5:从尾到头打印链表
- Andorid 反编译App
- 写一些关于自己的
- 致EVO:老兵永远不死,他只是凋零
- jQuery 中国省市两级联动(实用)
- Linux网络基本配置
- 单链表中的常见算法问题(剑指offer5/13/15/16/17)
- nginx + php 在window下的安装
- 定时器 T1 通过查询方式控制 LED1 周期性闪烁
- HTML中id、name、class 区别
- 流逝的岁月,致我们逝去的青春
- Windows快捷键大全
- Tomcat集群和Session共享的配置方法
- 【优先队列】【priority_queue】【getline】【istringstream】hdu 1873
- git使用方法备忘