线性表——单链表的概念

线性表---单链表

typedef struct node {
    ElemType data; //数据域
    struct node *next; //指针域
}LNode, *LinkList; // LinkList为指向LNode类型的指针

结点:数据元素的存储映像

链表:n个结点链接成起来形成一个链表,即为线性表的 链式存储结构

单链表: 结点中只包含一个指针域

  1. 头指针:指向链表中第一个结点(或为头结点、或为首元结点)的指针

  2. 头结点:在链表的首元结点之前附设的一个结点;数据域内只放表长等信息,它不计入表
    长度。其作用是统一空表、和非空链表的形式

  3. 首元结点:指链表中存储线性表第一个数据元素a1的结点

线性表的链式表示和实现

图1


(1)单链表的建立

  1. 先开辟头指针,建立头结点;
  2. 为每个新元素开辟存储空间,并赋值
  3. 将新结点链接到表尾

1、尾插法

/*例1:用尾插法建立26个字母的带表头结点的单链表*/
/*算法1-1*/
LinkList createLinkList1() //尾插法建立带表头结点的单链表
{ 
    LNode *L,*p,*s; //L头指针, p指向尾结点, s指向新结点
    L=(LNode *) malloc(sizeof(LNode)); //申请空白结点, L指向头结点
    L->next =NULL; //建立了头结点
    p=L; //p指向当前的尾结点
    for(i=1;i<=26;i++)
    {
        s=(LNode *) malloc(sizeof(LNode)); //申请空白结点, s指向
        s->data=i+‘a’-1; //给s->data 赋值
        p->next=s; s->next =NULL; //s指向的结点插入单链表的表尾
        p=s; //p总是指向当前链表的尾结点 , 等价于p=p->next
    }
    return L;
}
/*算法1-2*/
void createLinkList2(LinkList *L)
{
    //尾插法建立带表头结点的单链表 ,L指向头结点的指针的指针
    Lnode *p,*s; //p指向尾结点, s指向新结点
    *L=(LNode *) malloc(sizeof(LNode)); //申请空白结点, *L指向头结点
    if (*L==NULL) exit(0);
    *L->next =NULL; //建立了头结点
    p=*L; //p指向当前的尾结点
    for(i=1;i<=26;i++)
    { 
        s=(LNode *) malloc(sizeof(LNode)); //申请空白结点, s指向
        if (!s) exit(0);
        s->data=i+‘a’-1; //给s->data 赋值
        p->next=s; s->next =NULL; //s指向的结点插入单链表的表尾
        p=s; //p总是指向当前链表的尾结点 , 等价于p=p->next
    }
}

2、头插法

/*例2:用头插法建立26个字母的带表头结点的单链表*/
/*算法2-1*/
LinkList createLinkList1() /头插法建立带表头结点的单链表
{
    LNode *L,*s;     //L头指针, s指向新结点
    L=(LNode *) malloc(sizeof(LNode));  //申请空白结点, L指向头结点
    L->next =NULL; //建立了头结点
    for(i=26;i>=1;i--)
    { 
        s=(LNode *) malloc(sizeof(LNode));  //申请空白结点, s指向
        s->data=i+‘a’-1; //给s->data 赋值
        s->next=L->next;
        L->next =s; //s指向的结点插入头结点后面
    }
    return L;
}
/*算法2-2*/
void createLinkList2(LinkList *L)
{
    //L指向头结点的指针的指针
    LNode *s;     //p指向尾结点, s指向新结点
    *L=(LNode *) malloc(sizeof(LNode));  //申请空白结点, *L指向头结点
    if (*L==NULL) exit(0);
    *L->next =NULL; //建立了头结点
    for(i=26;i>=1;i--)
    { 
        s=(LNode *) malloc(sizeof(LNode));  //申请空白结点, s指向
        if (!s) exit(0);
        s->data=i+‘a’-1; //给s->data 赋值
        s->next=*L->next;
        *L->next =s; //s指向的结点插入头结点的后面
    }
}

(2)单链表的查找

思路:从头指针开始逐一查询

/*例3:单链表的查询*/
LNode* GetElem_L2(LinkList L, ElemType x)
{
    //在带头结点的单链表L中 查找元素值为x的结点,
    //若找到返回指向该结点的指针,否则返回NULL.
    LNode *p;
    p=L->next; //p指向首元结点
    while (p->data!=x && p)
    {
        p=p->next; //p指针后移
    }
    return p;
}

算法的时间复杂度:O(n)


(3)单链表的插入

在单链表中第i个位置插入一个元素x的示意图如下:

/*例4:单链表的插入*/
bool ListInsert_L(LinkList *L, int i, ElemType e)
{ 
    // L 为指向带头结点的单链表的头指针的指针
    //在链表中第i 个结点之前插入新的元素 e
    LNode *p; int j;
    p = *L; j = 0;
    while (p && j < i-1)
    {
         p = p->next; ++j;
    } // 寻找第 i-1 个结点
    if (!p || j > i-1)
    {
        return false; // i 大于n+1或者小于1
    }
    s = (LinkList) malloc(sizeof(LNode)) ; // 生成新结点
    if ( s == NULL)
    {
        return false;
    }
    s->data = e;
    s->next = p->next; p->next = s; // 插入
    return true;
} // LinstInsert_L

算法的时间复杂度:O(n)


(4)单链表的删除

/* 删除单链表 */
void deleteList(LNode *pHead)
{
    LNode *p1,*p2;
    p1 = pHead;//p1指向第一个结点
    while(p1->next != pHead)//当p1不指向头结点时
    {
        p2 = p1->next;
        free(p1);//删除第n个链表
        p1 = p2;
    }
    free(pHead);//删除头结点
}

算法时间复杂度:O(n) 

猜你喜欢

转载自blog.csdn.net/weixin_42562514/article/details/82794817
今日推荐