单链表专题一

来源:互联网 发布:红米手机清空所有数据 编辑:程序博客网 时间:2024/06/06 09:35
单链表总结
typedef struct ListNode{int val;ListNode *next;ListNode(int x): val(x), next(NULL){}} ListNode;/* *@brief: 打印单链表*/void printSList(const ListNode *head){const ListNode *ptr = head;while(ptr){cout << ptr->val << "  ";ptr = ptr->next;}cout << endl;}/* *@brief:用给出的数组以头插法创建单链表*/void createSList(ListNode *&head, int a[], int n){head = NULL;for(int i = 0; i < n; i++){ListNode *node = new ListNode(a[i]);node->next = head;head = node;}}/* 1 *@brief:单链表逆序*/void reverseList(ListNode *&head){if(NULL == head) return; //注意点一ListNode *ptr, *qptr;ptr = head;head = NULL;while(ptr){qptr = ptr; ptr = ptr->next; //标记下当前结点,然后移动指针qptr->next = head; head = qptr;}}/* 2 *@brief: 在单链表中查找倒数第k个元素*/ListNode* findKthFromEnd(ListNode *head, int k){if(NULL == head || 0 == k) return NULL; //注意点一ListNode *ptr = head;int count = 0;while(ptr && count != k){count++; ptr = ptr->next;}if(count < k) return NULL; //注意点二ListNode *qptr = head;while(ptr){qptr = qptr->next;ptr = ptr->next;}return qptr;}/* 3 *@brief: 找出链表的中间元素*/const ListNode *findMidElement(const ListNode *head){if(head == NULL) return NULL;const ListNode *oneStep = head;const ListNode *twoStep = head;while(twoStep->next){if(oneStep){ oneStep = oneStep->next; }if(twoStep){ twoStep = twoStep->next;if(NULL == twoStep) break; //注意点一}if(twoStep){ twoStep = twoStep->next; if(NULL == twoStep) break; //注意点二}}return oneStep;}/* 4 *@brief: 在单链表中删除值为x的结点 该结点不为最末尾的结点如果为最末尾结点要从头遍历一遍进行删除*/void deleteNodeInList(ListNode *&head, int x){if(head == NULL) return;ListNode *ptr = head->next;ListNode *prePtr = head;if(head->val == x){ //头指针的情况特殊处理ptr = head; head = head->next;delete ptr;return;}while(ptr){if(ptr->val == x) {prePtr->next = ptr->next; delete ptr; break;}prePtr = ptr;  //记录前一个结点ptr = ptr->next;}}/* 5 *@brief: 将两个不交叉的有序列合并成一个有序序列 用一的头结点作最终的头结点*/void combineTwoOrderLists(ListNode *&head1, ListNode *head2){ListNode *newHead = NULL;ListNode *tailList = NULL;ListNode *ptr;if(NULL == head1){head1 = head2;return;}if(head1 && head2){if(head1->val < head2->val){ ptr = head1; head1 = head1->next;}else{ptr = head2; head2 = head2->next;}//新的头结点newHead = ptr; tailList = newHead;newHead->next = NULL;}while(head1 && head2){if(head1->val < head2->val){ptr = head1; head1 = head1->next;}else{ptr = head2; head2 = head2->next;}ptr->next = NULL; tailList->next = ptr; tailList = tailList->next;}if(head1){ tailList->next = head1; }if(head2){ tailList->next = head2; }head1 = newHead; }/* 6 * @brief: 交换单链表任意两个元素 * @param: head头指针,k第k个元素第  x第x个元素 * @return: 返回尾指针*/void swapKthAndXthElem(ListNode *head, int k, int x){if(NULL == head || k <= 0 || x <= 0) return;ListNode *firstNode, *secondNode;ListNode *ptr = head;k--; x--; //注意点一while(ptr && k && x){ k--; x--; ptr = ptr->next; }firstNode = ptr; //找出第一个结while(ptr && k){ ptr = ptr->next; k--; }while(ptr && x){ ptr = ptr->next; x--; }if(k || x) return; //如果链表没有那么元素直接返回secondNode = ptr;//找出第二个结点swap(firstNode->val, secondNode->val);}/* 7 *@brief: 检测链表是否有环,如果链表有环,一个指针移动一步,另一个移动两步肯定有相交的情况*/bool checkCircle4List(ListNode *head){ListNode *oneStep, *twoStep;if(NULL == head) return false;oneStep = twoStep = head;do {oneStep = oneStep->next;twoStep = twoStep->next;if(NULL == twoStep) return false; //注意点一twoStep = twoStep->next;} while (oneStep != twoStep);return true;}/* 8 *@brief:判断两个单链表是否相交*/bool isTwoListsJoin(ListNode *head1, ListNode *head2){if(NULL == head1 || NULL == head2) return false;int m = 0, n = 0;ListNode *ptr;ptr = head1; //计算链表一的长度while(ptr){m++; ptr = ptr->next;}//计算链表二的长度ptr = head2;while(ptr){n++; ptr = ptr->next;} int tmpLen; //判断两个链表哪个更长 if(m > n){tmpLen = m - n; while(tmpLen){tmpLen--; head1 = head1->next;}}else{tmpLen = n - m;while(tmpLen){ tmpLen--; head2 = head2->next;}}//找出交点while(head1 && head2){//如果是计算两个单链表的相交点可以返回其指针if(head1 == head2) return true; head1 = head1->next;head2 = head2->next;}return false;}/* 9-1 * @brief: 模拟快速排序的链表排序算法 一次分割 * @param: head头指针,end尾指针,第一次end为NULL * @return: 返回尾指针*/ListNode* partation(ListNode *head, ListNode *end){if(head == NULL) return NULL;ListNode *iptr = head;//j = leftListNode *jptr = head->next;// i = left + 1while(jptr != end){if(jptr->val < iptr->val){iptr = iptr->next;//i++swap(jptr->val, iptr->val);}jptr = jptr->next;//j++}swap(head->val, iptr->val);//交换left与ireturn iptr;}/* 9-2 *@brief: 链表排序  如果元素重复太多算法会退化为n2 n的平方时间复杂度 *@param: head头指针,end尾指针,第一次end为NULL*/void sortList(ListNode *head, ListNode *end){if(head != end){ListNode *pos = partation(head, end);sortList(head, pos);sortList(pos->next, NULL);}}/* 10 *@brief: 删除单链表中相同的元素,前提相同元素相邻 *如果不相邻可以考虑用map或set(最好),或相排序再处理,如果元素范围固定可以考虑使用hash table*/void uniqueList(ListNode *head){if(NULL == head) return;ListNode *ptr, *qptr;ptr = head;while(ptr->next){if(ptr->val != ptr->next->val){ ptr = ptr->next;}else{qptr = ptr->next;ptr->next = ptr->next->next;delete qptr;}}}
0 0