算法之小细节(细节~链表的特殊结点~提升优化度)~反转链表删除排序链表中的重复元素
Posted 一乐乐
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法之小细节(细节~链表的特殊结点~提升优化度)~反转链表删除排序链表中的重复元素相关的知识,希望对你有一定的参考价值。
算法之小细节(细节~链表的特殊结点~提升优化度)~删除排序链表中的重复元素、反转链表
1,删除排序链表中的重复元素
(1)细节优化度高的代码:
public ListNode deleteDuplicates(ListNode head) { if(head == null || head.next == null) { return head; } else {
// head.next 用得好 head.next = deleteDuplicates(head.next);
//因为 是已经排序的链表,头结点即最小,只需要比较head 与新链表的头结点(head.next)就够了 return head.val == head.next.val ? head.next:head; } }
(2)自己写的 代码哈哈哈:
public ListNode deleteDuplicates(ListNode head) { // 头为空,或 只有一个头结点时 if (head == null || head.next == null) return head; // 递归得到头之后的链表 ListNode pre = deleteDuplicates(head.next); if(pre == null) return head; // 或者链表只有一个头结点时 if (pre.next == null) { if (pre.val == head.val) { //解释一下,为什么不能return head; //若 return head; 的话,而原来head 还指着老链条,出现重复结点啦 return pre; }else { head.next = pre; } } else { if (pre.val == head.val) { head.next = pre.next; }else { head.next = pre; } } return head; }
//很巧妙的 人家的思路:head.next = deleteDuplicates(head.next); 这样就相比较于自己的代码: // ListNode pre = deleteDuplicates(head.next); 好处在于不用判断 pre的情况,不用担心使用 pre.next == null 的情况,又判断 pre == null的情况 |
2,反转链表:
(1)细节优化度高的代码:
先说一下递归思路:
* 递归: 根据语义 reverseList(ListNode head),返回一条倒置的链表的头结点,
* 例如:原结点是 heda -》5-》4 -》3 -》2 -》1
* 利用语义的话 reverseList(head.next),得到了 head -》5 -》
* newHead -》1 -》2 -》3 -》4
* 细节:因为没有断链,原来的5 还是指导 4 身上, 即 newHead -》1 -》2 -》3 -》4 《- 5 《- head
* 所以,我们可以通过 5 的关系,拿到 4,调整4 指向5 ,
* 细节, 5是最后一个结点:它的next 需要指向空, 通过 head的关系拿到 5
public ListNode reverseList(ListNode head) { if(head == null) return null;//return head; 也一样 if(head.next == null) return head; if(head == null || head.next == null) return head; ListNode newHead = reverseList(head.next); //细节:这里用的是head.next.next(就是 4 这个结点的next指针),而不用 newHead这个变量,好处不用判断newHead(不为空时,就是4 这个结点) 是否为空, //因为咱如果是使用 newHead.next = head;(5 这个结点) 之前必须判断 newHead 是否为空,而使用 head.next(代表4 这个结点) 时,就可以避免判断情况 head.next.next = head; head.next = null; return newHead;return newHead; }
数据结构--单链表
实现了一个完整的单链表。
时长看一看,深入理解单链表的各个细节。
/* 设计一个算法求出单链表的倒数第m个结点,要求不得求出链表长度,不得对链表进行逆转,如果找到这样的结点就返回它的地址,如果没有就返回NULL。 */ #include <iostream> using namespace std; /**********************链表结构******************************/ template<typename DataType>class ListNode; template<typename DataType>class LinkList { public: LinkList() { head = new ListNode<DataType>(777); } LinkList(ListNode<DataType>* firstNode) { head = firstNode; } //析构函数 ~LinkList() { delete head; } bool insertNode(int index, DataType newData); bool insertNode(DataType newData); bool removeNode(ListNode<DataType>* q); ListNode<DataType>* findNode(DataType value); void cleanLink(); DataType getNodeData(const int index); int getLength(); ListNode<DataType>* getNode(int i); private: ListNode<DataType>* head; }; /*****************定义链表结点***********************/ template<typename DataType> class ListNode { public: ListNode() { next = NULL; } ListNode(const DataType item, ListNode<DataType>*nodeNext = NULL) { data = item; next = nodeNext; } ~ListNode() { next = NULL; } DataType getData() { return data; } ListNode<DataType>* getNext() { return next; } private: friend class LinkList<DataType>; ListNode<DataType>* next; DataType data; }; template<typename DataType> bool LinkList<DataType>::insertNode(int index, DataType newData) { ListNode<DataType>* p = head; int j; for (j = 1; j <= i - 1; j++) { p = p->next; if (NULL == p) { break;//如果指针为空,则不存在该结点或已到达表尾 } } if (NULL == p && j < (i - 1)) { std::cout << "插入位置无效" << std::endl; return false; } ListNode<DataType>* node = new ListNode<DataType>(newData); node->next = p->next; p->next = node; return true; } //链表表尾添加元素 template<typename DataType>bool LinkList<DataType>::insertNode(DataType newData) { ListNode<DataType>* p = head; ListNode<DataType>* node = new ListNode<DataType>(newData); if (NULL == node) { return false; } while (NULL != p->next) { p = p->next;//遍历单链表,找到表尾 } p->next = node; return true; } template<typename DataType> bool LinkList<DataType>::removeNode(ListNode<DataType>* q) { if (NULL == q) { std::cout << "待删除结点不存在!" << std::endl; return false; } ListNode<DataType>* tempPointer = head; while (tempPointer->next != q) { tempPointer = tempPointer->next; } tempPointer->next = q->next; delete q; return true; } template<typename DataType> ListNode<DataType>* LinkList<DataType>::findNode(DataType value) { ListNode<DataType>* currentPointer = head; //判定游标指针结点的值是否与value相等 while (NULL != currentPointer && value != currentPointer->next) { currentPointer = currentPointer->next; } if (NULL == currentPointer) { std::cout << "没有找到该结点!程序退出。" << std::endl; exit(1); } else { return currentPointer;//返回所找到的结点的指针 } } template<typename DataType> void LinkList<DataType>::cleanLink() { ListNode<DataType>* current = head; while (NULL != head->next) { current = head->next; head->next = current->next; delete current; } } template<typename DataType> DataType LinkList<DataType>::getNodeData(int index) { int linkLength = getLength(); if (index<1 || index > linkLength) { std::cout << "结点不存在!" << std::endl; return false; } else { ListNode<DataType>* pmove = head->next; for (int i = 1; i < index && NULL!=pmove; i++) { pmove = pmove->next; } return pmove->getData(); } } template<typename DataType> int LinkList<DataType>::getLength() { int count = 0; ListNode<DataType>* p = head->next; while (NULL != p) { p = p->next; count++; } return count; } template<typename DataType> ListNode<DataType>* LinkList<DataType>::getNode(int i) { ListNode<DataType>* p = head->next; int j; if (i<1 || i>getLength() - 1) { return false; } for (j = 1; j < i; j++) { p = p->next; if (NULL == p) { break; } } if (NULL == p && j < i - 1) { return false; } return p; } //查找倒数第m个结点 ListNode<int>* searchNodeM(LinkList<int>* link, int m) { ListNode<int>* p = link->getNode(1); if (NULL != p && m>0) { for (int i = 1; i < m; i++) { p = p->getNext(); if (NULL == p) { std::cout << "该链表没有倒数第m个结点" << std::endl; return NULL; } } } ListNode<int>* q = link->getNode(1); while (p->getNext() != NULL) { p = p->getNext(); q = q->getNext(); } return q; } int main() { LinkList<int>* head = new LinkList<int>(); int m; for (int i = 1; i <= 10; i++) { head->insertNode(i * 3); } cout << "请输入m的值:"; cin >> m; ListNode<int>* p = searchNodeM(head, m); for (int i = 1; i <= 10; i++) { cout << head->getNodeData(i) << " ,"; } cout << endl; cout << "倒数第" << m << "个结点:" << p->getData() << endl; cout << "Hello World C++ Algorithm." << endl; system("pause"); return 0; } /****** 注意 LinkList 里面都是 ListNode<DataType> 的形式。 *****/
以上是关于算法之小细节(细节~链表的特殊结点~提升优化度)~反转链表删除排序链表中的重复元素的主要内容,如果未能解决你的问题,请参考以下文章