单向链表

1.单向链表:
在链表把同一类型的结构体变量看成一个节点,用节点来表示每个同类型结构体变量,而每个节点中有一个数据域和一个指针域(单向链表),在双向链表中,每个节点中有一个prior域,一个数据域,一个指针域。
节点:指针域存放着下一个结构体的地址。
指针域:里面存放的是下一个节点(结构体变量)的地址,
数据域:里面存放的是该结构体变量的数据。
prior域:里面存放的是钱一个节点的地址。
单向链表的声明:
typedef struct Node
{
    data_t data;
    struct Node *next;
}Node;
typedef struct Node *LinkList;

如何判断一个链表是空链表还是这个链表不存在?单向链表

对于链表来说,头指针是必要的,而头结点不是必要。
单向链表的方法:头插法,尾插法。
头插法:把每个新来的节点插到头节点的后面去。
LinkList CreateListHead(LinkList L,int n)//创建链表(头插法)
{
    LinkList p;
    int i;
    srand(time(NULL));//初始化随机数种子
    for(i=0;i<n;i++)
    {
        p = (LinkList)malloc(sizeof(Node));
        p->data = rand()%100+1;
        p->next = L->next;
        L->next = p;
    }
    return L;
}

尾插法:直接把新来的节点插到这个链表的后面。
LinkList CreateListTail(LinkList L,int n)//创建链表(尾插法)
{
    LinkList p,r;
    int i;
    srand(time(NULL));
    r = L;
    for(i=0;i<n;i++)
    {
        p = (LinkList)malloc(sizeof(Node));
        p->data = rand()%100+1;
        r->next = p;
        r = p;
    }
    r->next = NULL;//链表封尾
    return L;
}
单向链表的操作:查找,插入,删除,清空。
查找:int GetElem(LinkList L,int i,data_t *data)//读取单链表的第i个元素
{
    int j;
    LinkList p;//工作指针
    p = L->next;
    j = 1;
    while(p && j<i)
    {
        p = p->next;//让p指向下一个节点
        j++;
    }
    if(!p)
    {
        printf("%d position error\n",i);
        return ERROR;
    }
    *data = p->data;
    return OK;
}

插入:int ListInsert(LinkList L,int i,data_t e)//插入新节点,使其成为第i个节点
{
    int j;
    LinkList p,s;
    p=L;
    j=1;
    while(p && j<i)//寻找i的位置
    {
        p=p->next;
        j++;
    }
    if(!p)//p为NULL
    {
        printf("%d position error\n",i);
        return ERROR;
    }
    //若if没有执行则证明位置有效,可以插入数据
    s=(LinkList)malloc(sizeof(Node));
    s->data=e;
    s->next=p->next;
    p->next=s;
    return OK;
}

删除:int ListDelete(LinkList L,int i,data_t *e)//删除第i个位置节点,数据由e获得
{
    int j;
    LinkList p,q;
    if(L->next==NULL)
    {
        printf("LinkList is Empty!\n");
        return ERROR;
    }
    p=L;
    j=1;
    while(p->next && j<i)
    {
        p=p->next;
        j++;
    }
    if(!(p->next))
    {
        printf("%d position error\n",i);
        return ERROR;
    }
    q=p->next;
    p->next=q->next;
    *e=q->data;
    free(q);
    return OK;
}

清空:int ClearList(LinkList L)//清空链表
{
    LinkList p,q;
    p=L->next;
    while(p)
    {
        q=p->next;
        free(p);
        p=q;
    }
    L->next=NULL;
    return OK;
}

链表的优缺点:
优点:1.插入删除元素非常简单,
2,表长动态变化,不会浪费内存或存储数据空间不足,、
缺点:读取数据麻烦,无法直接通过下标位置定位元素而需要借助工作指针。
链表的反序:(固定一个数,把后面的数用头插法来插入进去)。
找链表的最大元素。(要考虑表空和表中只有一个元素,然后再进行比较。


删除链表中的一个节点:
单向链表