单链表的理解及操作

一、对于结点的理解

​​​1.结点的定义

typedef struct Node
{
    ElemType data;
    struct Node *next;

}Node;

2.对该定义进行分解,首先得到:

struct 
{
    ElemType data;
    struct Node *next;

}Node;

分析:Node是一个结构体变量,内含两个成员变量;但这样定义有个缺点,就是当定义的结构体变量过多时,程序的可读性就下              降,为了提升可读性,对结构体加上标签;

3.对上述结构体加上标签得到:

struct Node
{
    ElemType data;
    struct Node *next;

}Node;

分析:struct Node成为自定义的数据类型,用它可以定义像Node这样的结构体变量,前者Node表示标签,后者表示结构体变               量,但是还可以更加简便;

4.对上述结构体简化:

typedef struct Node
{
    ElemType data;
    struct Node *next;

}Node;

分析:typedef是给struct Node这种数据类型起了一个别名叫Node,这时候就可以用Node来定义结构体变量;

5.对成员函数的理解:

   对于第二个成员函数:struct Node *next,表示的是结点指针,它指向的是下一个结点

二、对链表中函数参数的理解

1.为什么有的函数用ElemType *e,有的函数用ElemType e,还有LinkList *L和LinkList L?

分析:关于*e和e,问题在于我们要不要通过函数改变变量e的值,如果函数的参数是ElemType e, 那么在函数外部的e值将不会              因函数的操作而改变;如果函数参数为ElemType *e,则需要把e的地址传递给函数,实际上是改变了指针指向的内容;

           关于LinkList *L,LinkList是用来定义结构体指针的数据类型,因此 *L 是结构体指针,*L指向结构体,  

           那么L就是指向结构体指针的指针,是二级指针,当LinkList *L作形参的时候,传入的是结构体指针的地

           址,也就L指向的地址,对L解引用之后,相当于直接引用定义的结构体指针,从而实现对结构体指针修改;

           当使用LinkList L为形参时,传入的是结构体指针,可以使用它,但是没法修改它;

三、代码实现


/*
          项目名称:单链表的建立与基本操作
		  编译环境:VC++6.0
		  作者相关:。。。
		  最后修改:2019.5.18


          学习目标:1.建立单链表
		            2.熟悉各项基本操作的算法原理

          注意事项:1.初始化随机数种子:
                   (1)srand(time(0)),意思是随着时间的变化产生不同的随机数种子
                      配合rand()使用,产生真正的随机数
                   (2)若只使用rang(),系统先调用预设srand()函数产生种子,然后产
                      生伪随机序列,假设产生了10个不同的数,这10个数会一直循环


          常见错误:1.混淆define和typedef
                   2.在define后加分号


*/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define OK    1
#define ERROR 0
#define TRUE  1//多分号出现:后面程序if-else match error;
#define FALSE 0

typedef int   ElemType;
typedef bool  Status;



//定义链表结点结构体
typedef struct Node
{
    ElemType data;
    struct Node *next;

}Node,*LinkList;



//函数声明
Status InitList( LinkList *L );

Status ListEmpty( LinkList L );

Status ClearList( LinkList *L );

int    LengthList( LinkList L );

int    LocateElem( LinkList L, ElemType e );//查找链表里是不是有和e相等的元素,有就返回这个元素的位置

Status GetELem( LinkList L, int i, ElemType *e );//用e返回链表中第i个数据元素的值

Status ListInsert( LinkList *L, int i, ElemType e );//操作对象是指针,要改变指针的值,那就要用指针的指针

void   CreateListHead( LinkList *L, int n );//头插法

void   CreateListTail( LinkList *L, int n );//尾插法

Status ListDelete( LinkList *L, int i, ElemType *e );

Status   OutList( LinkList L );



int main()
{
    LinkList L1,L2,L3;
    ElemType e;
    int k;

    InitList(&L1);//把指针的地址传递给InitList
    for(int i=1;i<=10;i++)
        ListInsert(&L1,1,i);
    OutList(L1);

    GetELem(L1,3,&e);
    printf("第3个元素的值为:%d \n",e);

    k = LocateElem(L1,e);
    printf("%d 在链表中所处的位置为:%d \n",e,k);

    ListDelete(&L1,5,&e);
    OutList(L1);

    ClearList(&L1);

    ListEmpty(L1);

    CreateListHead(&L2,10);
    OutList(L2);

    CreateListTail(&L3,10);
    OutList(L3);

    return 0;
}


//初始化,建立头结点,L指向此头结点,该结点是结构体指针类型
Status InitList( LinkList *L )
{
    *L = (LinkList)malloc(sizeof(Node));//结点类型是LinkList
    if(!L)
        return ERROR;
    (*L)->next = NULL;
	    return OK;
}

Status ListEmpty( LinkList L )
{
    if(L->next)
        return FALSE;
    else
    {
        printf("the list is empty!\n");
        return TRUE;
    }
}
//清空链表:只保留头结点
Status ClearList( LinkList *L )
{
    LinkList p,q;

    p = (*L)->next;//p指向第一个结点
    while(p)//未到表尾
    {
        q = p->next;
        free(p);//释放p所指向结点的内存
        p = q;//p再指向下一个结点
    }

    (*L)->next = NULL;

    return OK;
}


int    LengthList( LinkList L )
{
    LinkList p;
    int count = 0;

    p=L->next;//p指向第一个结点

    while(p)
    {
        ++count;
        p = p->next;
    }

    return count;
}

//返回链表中与e相等元素的位置,没有则返回0
int    LocateElem( LinkList L, ElemType e )
{
    if(ListEmpty(L))
    {
        printf("the linklist is empty!\n");
        return ERROR;
    }

    LinkList p;
    int i=1;

    p = L->next;//p指向第一个结点
    while(p)
    {
        if(p->data == e)
            return i;
        else
        {
            p=p->next;
            ++i;
        }
    }

    if(p == NULL)
    {
        printf("与e相等的元素不存在!\n");
        return 0;
    }
}

//用e返回链表中第i个数据元素的值
Status GetELem( LinkList L, int i, ElemType *e )
{
	LinkList p;
	int j = 1;
	p = L->next;

	while(p&&j<i)//算法思想:工作指针后移
	{
	    p=p->next;
	    ++j;
	}

	if(!p||j>i)//1.链表为空;2.i的值小于1
        return ERROR;

	*e = p->data;
	return OK;
}

//在第i个元素之前插入数据e
Status ListInsert( LinkList *L, int i, ElemType e )
{    
    LinkList p,s;
    int j=1;
    p = *L;

    while(p&&j<i)
    {
        p=p->next;
        ++j;
    }

    if(!p||j>i)//i的值不存在
    {
        return ERROR;
    }

    s=(LinkList)malloc(sizeof(Node));
    s->data = e;
    s->next = p->next; 
    p->next = s;

    return OK;

}

//随机产生n个数,利用头插法完成链表的''整表创建''
void   CreateListHead( LinkList *L, int n )
{
    LinkList p;
    *L = (LinkList)malloc(sizeof(Node));
    (*L)->next = NULL;

    srand(time(0));//随时间产生不同的随机数种子

    for(int i=0;i<n;i++)
    {
        p = (LinkList)malloc(sizeof(Node));
        p->data = rand()%100+1;//任何数对100取余是0~99,进而取值范围是1~100
        p->next = (*L)->next;
        (*L)->next = p;
    }
}

//随机产生n个数,利用尾插法完成链表的''整表创建''
void   CreateListTail( LinkList *L, int n )
{
    LinkList p,s;
    *L = (LinkList)malloc(sizeof(Node));

    srand(time(0));
    p = *L;//p永远指向尾结点

    for(int i=0;i<n;i++)
    {
        s = (LinkList)malloc(sizeof(Node));
        s->data = rand()%100+1;
        p->next = s;
        p = s;//更新p的位置到尾结点
    }
    p->next = NULL;
}

//删除链表中第i个数据元素
Status ListDelete( LinkList *L, int i, ElemType *e )
{
    LinkList p,q;
    int j=1;
    p = *L;

    while(p->next&&j<i)//p有后继结点并且j<i
    {
        p=p->next;
        ++j;
    }

    if(!p||j>i)//i的值不存在
    {
        return ERROR;
    }
    
    q = p->next;
    p->next = q->next;

    *e = q->data;
    free(q);

    return OK;

}



Status   OutList( LinkList L )
{
    LinkList p;
    p=L->next;

    printf("The list is: \n");
    while(p)
    {
        printf("%d ",p->data);
        p=p->next;
	    
    }
    printf("\n");
    return OK;
}

猜你喜欢

转载自blog.csdn.net/Sruggle/article/details/90317948
今日推荐