引入

按照惯例,我们学习了如何初始化、插入、删除一个静态链表,那么静态链表打底有什么优缺点呢?链表还有什么高级玩法呢?
我们一起来看看~

静态链表的优缺点

  • **优点:**插入和删除时,只需要求改游标,不需要移动元素,从而改进了顺序存储结构中需要大量移动元素的缺点。
  • **缺点:**没有解决连续存储分配带来得表长难以确定的问题。

总之,静态链表是一个很好的尝试,在没有动态创建、释放内存空间得情况下,利用数组,完成了静态链表。

练习

创建一个20个元素的动态链表,然后快速找到其中间结点。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define LEN sizeof(struct Student)
#define STU_NUM 21

struct Student {
    int num;
    float score;
    struct Student * next;
};

struct Student *create(){
    srand((time(0)));
    struct Student *a , *b , *head;
    a=b=(struct Student *)malloc(LEN);
    int n=0;
    while(n<STU_NUM){
        n=n+1;
        a->num=n;
        a->score=rand()%100+1;
        if(n==1){
            head=a;
        }else{
            b->next=a;
            b=a;
        }
        a=(struct Student *)malloc(LEN);
    }
    b->next=NULL;
    return head;
}

void print_stu(struct Student *stu_p){
    while(stu_p!=NULL){
        printf("%d号:%3.1f分\n",stu_p->num,stu_p->score);
        stu_p=stu_p->next;
    }
}

struct Student *mid_p(struct Student *stu_p){
    struct Student *mid , *fast;
    mid=fast=stu_p;
    while(fast->next!=NULL){
        if(fast->next->next!=NULL){
            fast=fast->next->next;
            mid=mid->next;
        }else{
            fast=fast->next;
        }
    }
    return mid;
}

int main(){
    struct Student *stu_p , *mid;
    stu_p=create();
    print_stu(stu_p);
    mid=mid_p(stu_p);
    printf("中间结点是%d号%3.1f分\n",mid->num,mid->score);
    return 0;
}

运行结果
1号:49.0分
2号:69.0分
3号:12.0分
4号:6.0分
5号:45.0分
6号:3.0分
7号:40.0分
8号:74.0分
9号:67.0分
10号:27.0分
11号:83.0分
12号:89.0分
13号:84.0分
14号:26.0分
15号:61.0分
16号:68.0分
17号:77.0分
18号:87.0分
19号:63.0分
20号:84.0分
21号:45.0分
中间结点是11号83.0分

我们利用随机数,动态生成了链表,非常有趣的是,我们通过一个循环内移动两个指针,快速来快速遍历所有的链表,快速链表结束后,慢速指针就搞定了中间结点的位置。

尾巴

这是我的个人学习笔记,主要是应付考研复习使用,充斥着一些吐槽和个人观点,并不严谨,欢迎大家参考、指正。