C语言 数据结构--链表(2)

1、利用链表的几个基础操作算法完成以下功能:

(1)空链表L定义初始化(利用链表初始化函数)

(2)给链表赋初值:包含5个以上任意整数(利用头插法或尾插法)

(3)打印出链表L(自己设计打印函数)

(打印格式如:12  10  60  30  11  17  80)

(4)打印出链表的长度(利用求长度函数)

(5)打印出链表第3个元素

(6)x置(如在以上示例中,打印出30的位置是4,需要改写按值查找函数)

(7)在第4个元素位置前插入元素999

(8)打印出新链表:

(如:12  10  60  999  30  11  17  80)

(9)删除L的第3个元素

(10)打印出新链表L

(如:12  10  999  30  11  17  80

①单链表的存储结构

typedef struct Node
{
    int data;
    struct Node * next;
}Node,*LinkList;

②初始化单链表


void InitList(LinkList *L)
{
    *L = (LinkList)malloc(sizeof(Node));
    (*L)->next = NULL;
}

③尾插法创建单链表

//用尾插法创建单链表
void CreateTail(LinkList L)
{
    Node *r,*s;                  //定义两个指针变量,r指向链表的尾结点,s指向新创建的结点
    int flag=1;                  //定义一个标志变量,用于控制循环的结束
    int c;                       //定义一个整型变量,用于存储输入的数据
    r=L;                        //让r指向链表的头结点
    while(flag)                 //循环直到flag为0
    {
        scanf("%d",&c);         //从标准输入读取一个整数赋值给c
        if(c!=-99)                     //如果c不等于-99,表示还有数据需要插入链表
        {
            s = (Node*) malloc(sizeof(Node));  //动态分配一个结点的内存空间,并让s指向它
            s->data = c;                            //将c的值赋给s所指结点的数据域
            r->next = s;                             //将s所指结点链接到r所指结点的后面
            r=s;                                     //让r指向s,即更新尾结点的位置
        }
        else                                        //如果c等于-99,表示没有数据需要插入链表
        {
            flag = 0;                              //将flag置为0,结束循环
            r->next = NULL;                        //将尾结点的指针域置为NULL,表示链表结束
        }
    }
}

④实现链表的查找功能(按值查找  和 按位置查找

按位置查找

Node *Get(LinkList L,int i)
{
    int j;                                    //定义一个整型变量,用于记录当前遍历到的结点的位置
    Node *p;                                  //定义一个指针变量,用于遍历链表
    p=L;j=0;                                  //让p指向链表的头结点,并将j初始化为0
    if(i<=0) return NULL;                     //如果i小于等于0,表示无效的位置,返回NULL
    while((p->next!=NULL)&&(j<i))             //循环直到p指向NULL或者j等于i
    {
        p = p->next;                            //让p指向下一个结点
        j++;                                    //将j加1,表示移动了一个位置
    }
    if(i==j) return  p;                         //如果i等于j,表示找到了第i个结点,返回p
    else return NULL;                          //否则,表示没有找到第i个结点,返回NULL
}

按值查找

int Locate(LinkList L,int key)
{
    int i=0;                               //定义一个整型变量,用于记录当前遍历到的结点的位置
    Node *p;                              //定义一个指针变量,用于遍历链表
    p = L->next;                          //让p指向链表的第一个结点
    while(p!=NULL)                      //循环直到p指向NULL
    {
        if (p->data!=key)                //如果p所指结点的数据域不等于key
        {
            p = p->next;                 //让p指向下一个结点
            i++;                         //将i加1,表示移动了一个位置
        }
        else                            //否则,表示找到了值等于key的结点
            break;                      //跳出循环
    }
    return i;                          //返回i,表示找到的结点的位置,如果没有找到,返回0
}

⑤求链表的长度

int	ListLength(LinkList L)
{
    Node *p;             //定义一个指针变量,用于遍历链表
    int j;              //定义一个整型变量,用于记录链表的结点个数
    p=L->next;         //让p指向链表的第一个结点
    j=0;              //将j初始化为0
    while(p!=NULL)    //循环直到p指向NULL
    {
        p=p->next;     //让p指向下一个结点
        j++;          //将j加1,表示增加了一个结点
    }
    return j;     //返回j,表示链表的长度
}

⑥实现链表的插入功能

int InsList(LinkList L,int i,int e)

{
    Node *pre,*s;              //定义两个指针变量,pre指向插入位置的前一个结点,s指向新创建的结点
    int k;                     //定义一个整型变量,用于记录当前遍历到的结点的位置
    pre=L;                    //让pre指向链表的头结点
    k=0;                      //将k初始化为0
    while(pre!=NULL&&k<i-1)   //循环直到pre指向NULL或者k等于i-1
    {
        pre=pre->next;        //让pre指向下一个结点
        k=k+1;                //将k加1,表示移动了一个位置
    }
    if(!pre)                  //如果pre为空,表示插入位置不合理
    {
        printf("插入位置不合理!");
        return ERROR;
    }
    s=(Node*)malloc(sizeof(Node));        //动态分配一个结点的内存空间,并让s指向它
    s->data=e;                            //将e的值赋给s所指结点的数据域
    s->next=pre->next;                     //将s所指结点链接到pre所指结点的后面
    pre->next=s;                         //将pre所指结点链接到s所指结点的前面
    return OK;
}

⑦实现链表的删除功能

int DelList(LinkList L,int i)
{
    Node *pre,*r;              //定义两个指针变量,pre指向删除位置的前一个结点,r指向删除的结点
    int k;                     //定义一个整型变量,用于记录当前遍历到的结点的位置
    pre=L;                    //让pre指向链表的头结点
    k=0;                      //将k初始化为0
    while(pre->next!=NULL && k<i-1)   //循环直到pre的下一个结点为空或者k等于i-1
    {
        pre=pre->next;                //让pre指向下一个结点
        k=k+1;                        //将k加1,表示移动了一个位置
    }
    if(!(pre->next))                 //如果pre的下一个结点为空,表示删除位置不合理
    {
        printf("删除结点的位置i不合理!");
        return ERROR;
    }
    r=pre->next;                      //让r指向pre的下一个结点,即要删除的结点
    pre->next=pre->next->next;        //将pre所指结点链接到r所指结点的后面,即跳过r所指结点
    free(r);                          //释放r所指结点的内存空间
    printf("成功删除结点!");
    return OK;
}

⑧输出链表

void Display(LinkList L)
{
    L = L->next;                //让L指向链表的第一个结点
    while(L!=NULL)              //循环直到L指向NULL
    {
        printf("%d ",L->data);            //输出L所指结点的数据域的值
        L = L->next;                           //让L指向下一个结点
    }
}

完整代码和结果:

#include <stdio.h>
#include <malloc.h>
#define OK 1
#define ERROR -1

typedef struct Node
{
    int data;
    struct Node * next;
}Node,*LinkList;

//初始化
void InitList(LinkList *L)
{
    *L = (LinkList)malloc(sizeof(Node));
    (*L)->next = NULL;
}

//用尾插法创建单链表
void CreateTail(LinkList L)
{
    Node *r,*s;                  //定义两个指针变量,r指向链表的尾结点,s指向新创建的结点
    int flag=1;                  //定义一个标志变量,用于控制循环的结束
    int c;                       //定义一个整型变量,用于存储输入的数据
    r=L;                        //让r指向链表的头结点
    while(flag)                 //循环直到flag为0
    {
        scanf("%d",&c);         //从标准输入读取一个整数赋值给c
        if(c!=-99)                     //如果c不等于-99,表示还有数据需要插入链表
        {
            s = (Node*) malloc(sizeof(Node));  //动态分配一个结点的内存空间,并让s指向它
            s->data = c;                            //将c的值赋给s所指结点的数据域
            r->next = s;                             //将s所指结点链接到r所指结点的后面
            r=s;                                     //让r指向s,即更新尾结点的位置
        }
        else                                        //如果c等于-99,表示没有数据需要插入链表
        {
            flag = 0;                              //将flag置为0,结束循环
            r->next = NULL;                        //将尾结点的指针域置为NULL,表示链表结束
        }
    }
}

//查找
//按位置查找
Node *Get(LinkList L,int i)
{
    int j;                                    //定义一个整型变量,用于记录当前遍历到的结点的位置
    Node *p;                                  //定义一个指针变量,用于遍历链表
    p=L;j=0;                                  //让p指向链表的头结点,并将j初始化为0
    if(i<=0) return NULL;                     //如果i小于等于0,表示无效的位置,返回NULL
    while((p->next!=NULL)&&(j<i))             //循环直到p指向NULL或者j等于i
    {
        p = p->next;                            //让p指向下一个结点
        j++;                                    //将j加1,表示移动了一个位置
    }
    if(i==j) return  p;                         //如果i等于j,表示找到了第i个结点,返回p
    else return NULL;                          //否则,表示没有找到第i个结点,返回NULL
}

//按值查找
int Locate(LinkList L,int key)
{
    int i=0;                               //定义一个整型变量,用于记录当前遍历到的结点的位置
    Node *p;                              //定义一个指针变量,用于遍历链表
    p = L->next;                          //让p指向链表的第一个结点
    while(p!=NULL)                      //循环直到p指向NULL
    {
        if (p->data!=key)                //如果p所指结点的数据域不等于key
        {
            p = p->next;                 //让p指向下一个结点
            i++;                         //将i加1,表示移动了一个位置
        }
        else                            //否则,表示找到了值等于key的结点
            break;                      //跳出循环
    }
    return i;                          //返回i,表示找到的结点的位置,如果没有找到,返回0
}

//求带头结点的单链表L的长度
int	ListLength(LinkList L)
{
    Node *p;             //定义一个指针变量,用于遍历链表
    int j;              //定义一个整型变量,用于记录链表的结点个数
    p=L->next;         //让p指向链表的第一个结点
    j=0;              //将j初始化为0
    while(p!=NULL)    //循环直到p指向NULL
    {
        p=p->next;     //让p指向下一个结点
        j++;          //将j加1,表示增加了一个结点
    }
    return j;     //返回j,表示链表的长度
}

//在带头结点的单链表L中第i个位置插入值为e的新结点s
int InsList(LinkList L,int i,int e)

{
    Node *pre,*s;              //定义两个指针变量,pre指向插入位置的前一个结点,s指向新创建的结点
    int k;                     //定义一个整型变量,用于记录当前遍历到的结点的位置
    pre=L;                    //让pre指向链表的头结点
    k=0;                      //将k初始化为0
    while(pre!=NULL&&k<i-1)   //循环直到pre指向NULL或者k等于i-1
    {
        pre=pre->next;        //让pre指向下一个结点
        k=k+1;                //将k加1,表示移动了一个位置
    }
    if(!pre)                  //如果pre为空,表示插入位置不合理
    {
        printf("插入位置不合理!");
        return ERROR;
    }
    s=(Node*)malloc(sizeof(Node));     //动态分配一个结点的内存空间,并让s指向它
    s->data=e;                            //将e的值赋给s所指结点的数据域
    s->next=pre->next;                     //将s所指结点链接到pre所指结点的后面
    pre->next=s;                         //将pre所指结点链接到s所指结点的前面
    return OK;
}

int DelList(LinkList L,int i)
{
    Node *pre,*r;              //定义两个指针变量,pre指向删除位置的前一个结点,r指向删除的结点
    int k;                     //定义一个整型变量,用于记录当前遍历到的结点的位置
    pre=L;                    //让pre指向链表的头结点
    k=0;                      //将k初始化为0
    while(pre->next!=NULL && k<i-1)   //循环直到pre的下一个结点为空或者k等于i-1
    {
        pre=pre->next;                //让pre指向下一个结点
        k=k+1;                        //将k加1,表示移动了一个位置
    }
    if(!(pre->next))                //如果pre的下一个结点为空,表示删除位置不合理
    {
        printf("删除结点的位置i不合理!");
        return ERROR;
    }
    r=pre->next;                      //让r指向pre的下一个结点,即要删除的结点
    pre->next=pre->next->next;        //将pre所指结点链接到r所指结点的后面,即跳过r所指结点
    free(r);                 //释放r所指结点的内存空间
    printf("成功删除结点!");
    return OK;
}

void Display(LinkList L)
{
    L = L->next;               //让L指向链表的第一个结点
    while(L!=NULL)             //循环直到L指向NULL
    {
        printf("%d ",L->data);         //输出L所指结点的数据域的值
        L = L->next;                          //让L指向下一个结点
    }
}

int main() {
    int len,pos1,pos2;
    int loc1,e;
    int loc2;
    LinkList L;
    Node *p;
    int  p1;
    InitList(&L);
    printf("请输入元素(输入‘-99’时结束):\n");
    CreateTail(L);
    printf("链表:\n");
    Display(L);
    len = ListLength(L);
    printf("\n链表的长度为:%d",len);
    printf("\n请输入要查找元素的位置:");
    scanf("%d",&pos1);
    p = Get(L,pos1);
    printf("链表位置为%d的元素为:%d",pos1,p->data);
    printf("\n请输入要查找位置的元素:");
    scanf("%d",&pos2);
    p1 = Locate(L,pos2);
    printf("%d在链表的位置为:%d",pos2,p1);
    printf("\n请输入要插入元素的位置和值:");
    scanf("%d %d",&loc1,&e);
    InsList(L,loc1,e);
    printf("插入元素后的链表:");
    Display(L);
    printf("\n请输入要删除元素的位置:");
    scanf("%d",&loc2);
    DelList(L,loc2);
    printf("删除元素后的链表:");
    Display(L);
    return 0;
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值