数据结构(一)线性表单链表试题
题目
快速找到未知长度的单链表的中间节点
解决思路
(一)使用一个指针,先索引一遍获取总长度,再取长度一半去循环获取到中间值
算法复杂度: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; }
效果预览