哈佛cs50公开课,list1链表相关程序

很纳闷,上次发的fifteen竟然说包含不适内容,就是程序而已啊,莫名其妙。

这个就是公开课上链表的程序,稍微改了下,没用他的头文件,同时添加了注释。用codeblocks编译通过。

链表这个确实挺麻烦,并不是不能理解,而是具体实施该怎么做。

主要要理解头指针,头节点,第一个节点的含义和怎么表示。

下面是程序:

/*
一个数字链表。可以实现插入(按大小),查询,删除等功能
输入1,用于删除;
输入2,用于寻找;
输入3,用于插入;
输入4,用于遍历;
输入0,用于退出;
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//定义链表
typedef struct node
{
    int n;//注意这个n,和平时int n区别开来
    struct node *next;
}
node;
//头指针
node *first=NULL;
//声明函数
void delete(void);
void find(void);
void insert(void);
void traverse(void);
int getint(void);//代替头文件里的GetInt
//主函数
int
main()
{
    int c;
    do
    {
        printf("\n菜单\n\n"
                "输入1,删除链表内数字\n"
                "输入2,寻找链表内数字\n"
                "输入3,插入数字到链表中(自动排序)\n"
                "输入4,遍历链表\n"
                "输入0,退出\n");
        //输入
        printf("请输入命令:");
        c=getint();
        //分类
        switch(c)
        {
            case 1:delete();break;
            case 2:find();break;
            case 3:insert();break;
            case 4:traverse();break;
            default:printf("请按照提示输入命令\n");
        }
    }
    while(c!=0);
    //释放链表空间
    node *ptr=first;
    while(ptr!=NULL)
    {
        node *predptr=ptr;
        ptr=ptr->next;
        free(predptr);
    }
    return 0;
}


//getint
int getint(void)
{
    int p,m,num;
    while(1)
    {
        p=scanf("%d",&num);//scanf的返回值
        while((m=getchar())!='\n'&&m!=EOF);//清除输入缓存
        if(p==1)//返回值是数字则为1,否则是其它的
            return num;
        else
            printf("请确保输入的是整数,再试一次:");
    }
}


//delete
void
delete(void)
{
    printf("输入要删除的数字:");
    int n=getint();

    node *ptr=first;//为什么不直接用first
    node *predptr=NULL;//

    while(ptr!=NULL)//最后节点
    {
        if(ptr->n==n)//链表里面有这个数,这2个n是不一样的,一个是定义链表里的数据,一个是输入的数字
        {
            //if(ptr->n==first->n)
            if(ptr==first)//ptr是在变化的,因为是个while循环,判断ptr变化了没?用这个if(ptr->n==first->n)可以不?实验后可以
            {
                first=ptr->next;
                free(ptr);
            }
            else//在中间或是尾部
            {
                predptr->next=ptr->next;//predptr在这里已经不是NULL了,第一个节点不相等就会执行下面的predptr=ptr;而相等就不会进行这一步
                free(ptr);
            }
            break;
        }
        else
        {
            predptr=ptr;
            ptr=ptr->next;//同上面联系起来看,predptr与ptr相隔1个节点
        }
    }
    if(ptr==NULL)
        printf("你所要删除的数字不存在\n");
    traverse();
}

//insert
void
insert(void)
{
    node *newptr=malloc(sizeof(node));
    if(newptr==NULL)
        {
            printf("申请空间出错\n");
            return;
        }
    printf("输入插入的数字:");
   //插入的链表节点
    newptr->n=getint();
    newptr->next=NULL;
    //如果链表是空的,则直接是newptr
    if(first==NULL)
        first=newptr;//为什么不是first->next=newptr?因为first单纯是个指针,就是第一个节点,first->next是第二个节点了。
    //插入链表头部
    else if(newptr->n<first->n)//first->n?第一个数据?
    {
        newptr->next=first;//为什么不是first->next?同上,相当于将newptr和first链接起来
        first=newptr;
    }
    //插入中间或底部
    else
    {
        node *predptr=first;//为什么不直接用first而是新建一个指针predptr呢?
        while(1)
        {
            //是否重复
            if(predptr->n==newptr->n)
            {
                free(newptr);
                break;
            }
            //判断是否在尾部
            else if(predptr->next==NULL)
            {
                predptr->next=newptr;
                break;
            }
            //在中间的情况
            else if(predptr->next->n>newptr->n)//predptr->next->n?
            {
                newptr->next=predptr->next;
                predptr->next=newptr;
                break;
            }
           //循环
            predptr=predptr->next;
        }
    }
    //遍历一下
    traverse();
}

//find
void
find(void)
{
    printf("输入要查找的数字:");
    int n=getint();
    node *ptr=first;
    while(ptr!=NULL)
    {
        if(ptr->n==n)
        {
            printf("\n已找到%d\n",n);
            usleep(100000);
            break;
        }
        ptr=ptr->next;
    }
     if(ptr==NULL)
        printf("你所要寻找的数字不存在\n");
}

//traverse
void
traverse(void)
{
    printf("现在列表中存在的数据有:");
    node *ptr=first;
    while(ptr!=NULL)
    {
        printf("%d ",ptr->n);
        ptr=ptr->next;
    }
    fflush(stdout);
    usleep(100000);
    printf("\n\n");
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值