线性表-单链表-快慢指针

快慢指针:

定义两个指针,一个快,一个慢,可以有多种用途。例如:快速找到位置长度单链表中的中间结点;对于循环链表中利用快慢指针也可以判断是否存在环。

快速找到位置长度单链表中的中间结点

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;
}
View Code

 

posted @ 2020-02-20 16:15  kkzhang  阅读(412)  评论(0编辑  收藏  举报