首页 终生学习

简单贴一下链表的建立等常用操作

链表定义

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。

源代码

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

//输入格式   1   89
//           2   99
//           0   0
struct Student {
    long num;
    float score;
    struct Student *next;
};
int n;
struct Student *creat();
struct Student *del(struct Student *head,long num);
struct Student *insert(struct Student *head,struct Student *stu);
void print(struct Student *head);
int main() {

    struct Student *head,*stu;
    long del_num;
    printf("请输入数据:\n");
    head=creat();
    print(head);
    printf("请输入要删除的数字:\n");
    scanf("%ld",&del_num);
    while(del_num!=0) {            //当输入的学号为0时结束循环
        head=del(head,del_num); //删除结点后返回链表的头地址
        print(head);            //输出全部结点
        printf("请输入要删除的数字:\n");
        scanf("%ld",&del_num);
    }
    printf("请输入要添加的数据:\n");
    stu=(struct Student *)malloc(LEN);  //开辟一个新结点
    scanf("%ld %f",&stu->num,&stu->score);
    while(stu->num!=0) {            //当输入的学号为0时结束循环
        head=insert(head,stu);    //返回链表的头地址,赋值给head
        print(head);            //输出全部结点
        printf("请输入要添加的数据:\n");
        stu=(struct Student *)malloc(LEN);  //开辟一个新结点
        scanf("%ld %f",&stu->num,&stu->score);
    }
    return 0;
}

struct Student *creat(void) { //返回一个指向链表头的指针
    struct Student *head;
    struct Student *p1,*p2;
    n=0;
    p1=p2=(struct Student *)malloc(LEN);//开辟一个新的结点使p1,p2指向它
    scanf("%ld %f",&p1->num,&p1->score);//输入第1个学生的学号和成绩
    head=NULL;
    while(p1->num!=0) {
        n=n+1;
        if(n==1) {    //如果这个结点是头结点,那么就把head指向p1
            head=p1;
        } else {
            p2->next=p1;  //如果不是,则使这个结点的next指向新开辟结点
        }
        p2=p1;            //使p2指向刚才建立的结点
        p1=(struct Student *)malloc(LEN);//生成新的结点 ,使p1指向它
        scanf("%ld %f",&p1->num,&p1->score);
    }
    p2->next=NULL;    //当p2是表尾时,把NULL赋值给next,结束链表建立
    return(head);
}

void print(struct Student *head) {
    struct Student *p;
    printf("\nNow,These %d records are:\n",n);
    p=head;
    if(head!=NULL) {
        do {
            printf("%ld %5.1f\n",p->num,p->score);
            p=p->next;
        } while(p!=NULL);
    }
}

struct Student *insert(struct Student *head,struct Student *stu) {
    struct Student *p0,*p1,*p2;
    p1=head;        //使p1指向头结点
    p0=stu;            //指向要插入的结点
    if(head==NULL) { //原来的链表是空表
        head=p0;
        p0->next=NULL;
    } else {
        while((p0->num>p1->num)&&(p1->next!=NULL)) {
            p2=p1;        //使p2指向刚才p1指向的结点
            p1=p1->next;//p1后移一个结点
        }
        if(p0->num<p1->num) {
            if(head==p1) {
                head=p0;    //插到原来第1个结点之前
            } else {
                p2->next=p0;//插到p2指向的结点之后
                p0->next=p1;
            }
        } else {
            p1->next=p0;
            p0->next=NULL;  //插到最后的结点之后
        }
    }
    n=n+1;
    return(head);        //结点数+1
}

struct Student *del(struct Student *head,long num) {
    struct Student *p1,*p2;
    if(head==NULL) {
        printf("这是一张空表\n");
        return(head);
    }
    p1=head;               //使p1指向第1个结点
    while(num!=p1->num&&p1->next!=NULL) { //p1指向的不是所要找的结点且后面还有结点
        p2=p1;
        p1=p1->next;       //p1向后移一个结点
    }
    if(num==p1->num) {      //找到了
        if(p1==head) {      //若p1指向的是首结点,把第2个结点地址赋予head
            head=p1->next;
        } else {             //否则将下一个结点地址赋给前一结点地址
            p2->next=p1->next;
        }
        printf("删除:%ld\n",num);
        n=n-1;
    } else {
        printf("%ld没有找到\n",num);//找不到该结点
    }
    return(head);

}



文章评论

目录