1、线性表的链式存储结构

每个元素多用一个位置来存放指向下一个元素位置的指针,依次类推,可以找到所有的元素。链式存储中,除了要存储数据本身外,还要存储它的后继元素的存储地址(指针)。

   数据域:存储数据信息的域;

   指针域:存储直接后继位置的域。

   这两部分信息组成数据元素称之为存储映像,节点Node。链表中每个结点中只包含一个指针域,为单链表。链表中的第一个结点的存储位置叫做头指针,最后一个结点指针为空。

线性表-链式存储结构

2、头节点和头指针(头节点不是必须的)

    头指针:

1)头指针是指链表指向第一个结点的指针,若链表有头节点,则是指向头结点的指针。
2)头指针具有标识作用,常用头指针冠以链表的名字(指针变量的名字)。
3)无论链表是否为空,头指针均不为空。
4)头指针是链表的必要元素。

   头节点:

1)放在第一个元素的结点之前,其数据域一般无意义(可以用来存放链表长度)
2)为了操作的统一方便设立(在第一元素结点前插入和删除第一结点与其他结点操作统一)
3)头节点不一定是链表的必要元素。

线性表-链式存储结构 

3、带头结点的单链表实现

C语言中可以用结构指针来描述单链表:

typedef int ElemType;

typedef struct Node {
    ElemType data;    //数据域
    struct Node* Next;//指针域
}Node, *LinkList;
//结点由存放数据的数据域和存放后继结点地址的指针域组成

 

单链表的插入:

线性表-链式存储结构

//单链表的插入
STATUS ListInsert(LinkList* L, int i, ElemType e)//L是指向头节点的二级指针
{
    if ((L == NULL) || (i > (*L)->data + 1))
    {
        return 0;
    }

    int j=1;
    LinkList p = *L;

    while (p && (j < i))//找到要插入的位置
    {
        p = p->Next;
        j++;
    }
    LinkList n = (LinkList)malloc(sizeof(Node));
    n->data = e;
    n->Next = p->Next;
    p->Next = n;

    (*L)->data++;   //头节点的数据域,表示当前链表的长度
    return 1;
}

单链表的删除

线性表-链式存储结构

//单链表的删除
STATUS ListDelete(LinkList* L, int i, ElemType* e)
{
    if (L == NULL || i > (*L)->data + 1)
        return 0;
    int j = 1;
    LinkList p = (*L);
    while (p&&j<i)
    {
        p = p->Next;
        j++;
    }
    LinkList q = p->Next; //要删除的结点
    *e = q->data;
    p->Next = q->Next;

    free(q);
    (*L)->data--;
    return 1;
}
//四个基本操作,初始,清空,判断是否为空,获取长度
//初始化带有头结点的链表
Status InitList(LinkList* L)
{
    *L = (LinkList)malloc(sizeof(Node));    //使头指针指向头结点
    if (*L == NULL)    //内存分配失败
        return ERROR;
    (*L)->next = NULL;    //指针域为空
    (*L)->data = 0;    //头结点数据域用来存放链表长度
    return OK;
}

//清空链表(不会清除头结点)
Status ClearList(LinkList* L)
{
    LinkList q, p;
    q = (*L)->next;    //是q指向第一个结点
    while (q)
    {
        p = q;
        q = q->next;
        free(p);
    }
    (*L)->next = NULL;
    return OK;
}

//判断链表是否为空
Status ListEmpty(LinkList L)
{
    if (L->next)
        return FALSE;
    return TRUE;
}

//获取列表长度
int ListLength(LinkList L)
{
    /*
    int length=0;
    LinkList q=L;
    while (q=q->next)
        length++;
    return length;
    */
    return L->data;
}
#include <stdio.h>
#include <stdlib.h>

typedef int ElemType;
typedef int STATUS;

typedef struct Node {
    ElemType data;    //数据域
    struct Node* Next;//指针域
}Node, *LinkList;
//结点由存放数据的数据域和存放后继结点地址的指针域组成

//单链表的插入
STATUS ListInsert(LinkList* L, int i, ElemType e)//L是指向头节点的二级指针
{
    if ((L == NULL) || (i > (*L)->data + 1))
    {
        return 0;
    }

    int j=1;
    LinkList p = *L;

    while (p && (j < i))//找到要插入的位置
    {
        p = p->Next;
        j++;
    }
    LinkList n = (LinkList)malloc(sizeof(Node));
    n->data = e;
    n->Next = p->Next;
    p->Next = n;

    (*L)->data++;  //头节点的数据域,表示当前链表的长度
    return 1;
}

//单链表的删除
STATUS ListDelete(LinkList* L, int i, ElemType* e)
{
    if (L == NULL || i > (*L)->data + 1)
        return 0;
    int j = 1;
    LinkList p = (*L);
    while (p&&j<i)
    {
        p = p->Next;
        j++;
    }
    LinkList q = p->Next; //要删除的结点
    *e = q->data;
    p->Next = q->Next;

    free(q);
    (*L)->data--;
    return 1;
}

int main()
{
    LinkList L=(LinkList)malloc(sizeof(Node));
    L->Next = NULL;
    L->data = 0;
    for (int i = 1; i <= 10; i++)
    {
        ListInsert(&L, i, i * i);
    }
    LinkList p = L->Next;
    while (p)
    {
        printf_s("%d ", p->data);
        p = p->Next;
    }
    printf_s("\n");
    int j,e;
    printf_s("请输入要删除第几个结点\n");
    scanf_s("%d",&j);
    ListDelete(&L, j, &e);
    printf_s("删除的结点为:%d\n", e);
    printf_s("删除后的链表为:\n");
    p = L->Next;
    while (p)
    {
        printf_s("%d ", p->data);
        p = p->Next;
    }
    return 1;
}
View Code

相关文章: