线性表-单链表-快慢指针
快慢指针:
定义两个指针,一个快,一个慢,可以有多种用途。例如:快速找到位置长度单链表中的中间结点;对于循环链表中利用快慢指针也可以判断是否存在环。
快速找到位置长度单链表中的中间结点
1)使用一个指针,先索引一遍获取总长度,再取长度一半去循环获取到中间值;O(3L/2)。
2)使用两个指针,快指针和慢指针,快指针一次向前走2格,慢指针一次走一格,当快指针走完全程,慢指针正好走在中间;O(L/2)。
代码实现:
//快速查找中间元素 int FindMidEle(LinkList L, Elemtype *e) { LinkList search, middle; //search是快指针,middle是慢指针 int i=0; if (L == NULL || e == NULL) return i; search = middle = L; while (search->next) { if (search->next->next!=NULL) //快指针是慢指针的两倍速度 { search = search->next->next; middle = middle->next; } else //是针对奇数个元素,再次进行操作,是之能够退出 { search = search->next; middle = middle->next; //奇数需要再次向后取一位,才会到达中间 } i++; } *e = middle->data; return i; }
#include <stdio.h> #include <stdlib.h> typedef int ElemType; typedef int STATUS; typedef struct Node { ElemType data; //数据域 struct Node* Next;//指针域 }Node, *LinkList; //结点由存放数据的数据域和存放后继结点地址的指针域组成 //单链表的插入 STATUS ListInsert(LinkList* L, int i, ElemType e)//L是指向头节点的二级指针 { if ((L == NULL) || (i > (*L)->data + 1)) { return 0; } int j=1; LinkList p = *L; while (p && (j < i))//找到要插入的位置 { p = p->Next; j++; } LinkList n = (LinkList)malloc(sizeof(Node)); n->data = e; n->Next = p->Next; p->Next = n; (*L)->data++; //头节点的数据域,表示当前链表的长度 return 1; } //单链表的删除 STATUS ListDelete(LinkList* L, int i, ElemType* e) { if (L == NULL || i > (*L)->data + 1) return 0; int j = 1; LinkList p = (*L); while (p&&j<i) { p = p->Next; j++; } LinkList q = p->Next; //要删除的结点 *e = q->data; p->Next = q->Next; free(q); (*L)->data--; return 1; } void CreatListHead(LinkList* L, int n) { LinkList p; int i; srand(time(0)); *L = (LinkList)malloc(sizeof(Node)); (*L)->Next = NULL; for (i = 0; i < n; i++) { p = (LinkList)malloc(sizeof(Node)); p->data = rand() % 10 + 1; p->Next = (*L)->Next; (*L)->Next = p; } } void CreatListEnd(LinkList* L, int n) { LinkList p, r; //创建头结点 *L = (LinkList)malloc(sizeof(Node)); (*L)->data = 0; (*L)->Next = NULL; p = *L; srand(time(0)); for (int i = 0; i < n; i++) { r = (LinkList)malloc(sizeof(Node)); r->data = rand() % 10 + 1; r->Next = p->Next; p->Next = r; p = r; //p指向最后一个结点 (*L)->data++; } } int FindMidEle(LinkList L, ElemType* e) { LinkList search, middle; int i = 0; if (L == NULL || e == NULL) return 0; search = middle = L; while (search->Next) { if (search->Next->Next != NULL) { search = search->Next->Next; middle = middle->Next; } else { search = search->Next; middle = middle->Next; } i++; } *e = middle->data; return i; } int main() { //LinkList L=(LinkList)malloc(sizeof(Node)); //L->Next = NULL; //L->data = 0; //for (int i = 1; i <= 10; i++) //{ // ListInsert(&L, i, i * i); //} LinkList L; CreatListEnd(&L, 10); LinkList p = L->Next; while (p) { printf_s("%d ", p->data); p = p->Next; } printf_s("\n"); int j,e; printf_s("请输入要删除第几个结点\n"); scanf_s("%d",&j); ListDelete(&L, j, &e); printf_s("删除的结点为:%d\n", e); printf_s("删除后的链表为:\n"); p = L->Next; while (p) { printf_s("%d ", p->data); p = p->Next; } int i=FindMidEle(L,&e); printf_s("中间元素为第%d结点%d\n",i,e); return 1; }