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


    快慢指针:

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

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

    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("
    ");
        int j,e;
        printf_s("请输入要删除第几个结点
    ");
        scanf_s("%d",&j);
        ListDelete(&L, j, &e);
        printf_s("删除的结点为:%d
    ", e);
        printf_s("删除后的链表为:
    ");
        p = L->Next;
        while (p)
        {
            printf_s("%d ", p->data);
            p = p->Next;
        }
        int i=FindMidEle(L,&e);
        printf_s("中间元素为第%d结点%d
    ",i,e);
        return 1;
    }
    View Code
  • 相关阅读:
    在C#中子线程如何操作主窗口线程上的控件
    创建数据透视表数据包含合并单元格
    sql,nosql
    Enthought科学计算,数据分析
    程序员常去的14个顶级开发社区
    Windows查看进程taskList,终止进程tskill
    Pandas库之DataFrame
    centos下chm阅读器
    c++回调函数
    __NSAutoreleaseNoPool(): ... utoreleased with no pool in place
  • 原文地址:https://www.cnblogs.com/lemonzhang/p/12336200.html
Copyright © 2020-2023  润新知