数据结构(一)线性表单链表试题

题目

快速找到未知长度的单链表的中间节点

解决思路

(一)使用一个指针,先索引一遍获取总长度,再取长度一半去循环获取到中间值

算法复杂度:O(L)+O(L/2) = O(3L/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;
}

全部代码实现

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>

#define ERROR 0 
#define OK 1
#define FALSE 0
#define TRUE 1

typedef int Status;
typedef int Elemtype;

typedef struct Node
{
    Elemtype data;
    struct Node* next;
}Node;

typedef struct Node* LinkList;

//初始化链表
Status InitList(LinkList* L);
//创建元素
Elemtype CreateElem(int n);
//尾插法创建链表
Status CreateListEnd(LinkList* L, int n);
//头插法创建链表
Status CreateListHead(LinkList* L, int n);
//清空链表
Status ClearList(LinkList* L);
//判断链表是否为空
Status ListEmpty(LinkList L);
//打印链表
void PrintList(LinkList L);
//快速查找中间元素
int FindMidEle(LinkList L, Elemtype *e);

void ShowMenu()
{
    system("cls");
    printf("----------------------\n");
    printf("0.Exit\n");
    printf("1.InitList\n");
    printf("2.CreateListByHead\n");
    printf("3.CreateListByEnd\n");
    printf("4.ShowList\n");
    printf("5.findMidElem\n");
    printf("6.clear list\n");
    printf("7.clear screen\n");
    printf("----------------------\n");
}

int main()
{
    LinkList L=NULL;
    int n;
    Elemtype e;
    srand(time(0));    //生成随机数种子

    while (1)
    {
        ShowMenu();
        while (1)
        {
            scanf("%d", &n);
            if (n == 0)
                return 0;
            if (n == 7)
                break;
            if (n != 1 && L == NULL)
            {
                printf("you must intilist first\n");
                continue;
            }
            if (n == 1)
                if (InitList(&L))
                    printf("InitList successful\n");
                else
                    printf("InitList failure\n");
            else if (n == 2)
            {
                printf("please choose the number to create list:");
                scanf("%d", &n);
                if (CreateListHead(&L, n))
                    printf("CreateListHead successful\n");
                else
                    printf("CreateListHead failure\n");
            }
            else if (n == 3)
            {
                printf("please choose the number to create list:");
                scanf("%d", &n);
                if (CreateListEnd(&L, n))
                    printf("CreateListEnd successful\n");
                else
                    printf("CreateListEnd failure\n");
            }
            else if (n == 4)
                PrintList(L);
            else if (n == 5)
            {
                int index = FindMidEle(L, &e);
                if (index != 0)
                    printf("find middle element:%d in:%d\n", e, index);
                else
                    printf("find failure! you must inital list and create element first\n");
            }
            else if (n == 6)
                if (ClearList(&L))
                    printf("ClearList success\n");
                else
                    printf("ClearList failure\n");
        }
    }
    system("pause");
    return 0;
}

//初始化链表
Status InitList(LinkList* L)
{
    if (*L == NULL)
    {
        *L = (LinkList)malloc(sizeof(Node));
        if (*L == NULL)
            return ERROR;
        (*L)->next = NULL;
    }
    else
        if (!ListEmpty(*L))
            ClearList(L);
    return OK;
}

Elemtype CreateElem(int n)
{
    return rand() % (n*n);
}

//尾插法创建链表,创建n个随机元素
Status CreateListEnd(LinkList* L, int n)
{
    LinkList q, p;
    q = *L;

    if ((*L) == NULL || n < 1)
        return ERROR;

    if (!ListEmpty(*L))
        ClearList(L);

    for (int i = 0; i < n;i++)
    {
        p = (LinkList)malloc(sizeof(Node));
        p->data = CreateElem(n);
        q->next = p;
        q = p;
    }
    q->next = NULL;

    return OK;
}

//头插法创建链表
Status CreateListHead(LinkList* L, int n)
{
    LinkList q, p;
    q = *L;

    if ((*L) == NULL || n < 1)
        return ERROR;

    if (!ListEmpty(*L))
        ClearList(L);

    for (int i = 0; i < n; i++)
    {
        p = (LinkList)malloc(sizeof(Node));
        p->data = CreateElem(n);
        p->next = q->next;
        q->next = p;
    }

    return OK;
}

//清空链表(不会清除头结点)
Status ClearList(LinkList* L)
{
    LinkList q, p;
    q = (*L)->next;    //是q指向第一个结点
    while (q)
    {
        p = q;
        q = q->next;
        free(p);
    }
    (*L)->next = NULL;
    return OK;
}

//判断链表是否为空
Status ListEmpty(LinkList L)
{
    if (L->next)
        return FALSE;
    return TRUE;
}

//打印链表
void PrintList(LinkList L)
{
    LinkList q = L;
    while (q=q->next)
        printf("%d ", q->data);
    printf("\n");
}

//快速查找中间元素
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;
}

效果预览

 

posted @ 2018-08-05 10:33  山上有风景  阅读(1105)  评论(0编辑  收藏  举报