单链表

线性表的链式存储结构——单链表

单链表是指通过一组任意的存储单元来存储线性表中的数据元素。为了建立数据元素之间的线性关系,对每个链表结点,除存放元素自身信息外,还需要存放一个指向其后继的指针。

data next

单链表中结点类型的描述如下:

typedef struct LNode {            //定义单链表结点类型
    ElemType data;                //数据域
    struct LNode* next;           //指针域
}LNode,*LinkList;    

 

头结点和头指针的区分:不管带不带头结点,头指针都始终指向链表的第一个结点,而头结点是带头结点的链表中的第一个结点,结点内通常不存储信息。

引入头结点后,可以带来两个优点:

①由于第一个数据结点的位置被存放头结点的指针域中,因此在链表的第一个位置上的操作和在表的其他位置上的操作一致,无须进行特殊处理。

②无论链表是否为空,其头指针都指向头结点的非空指针(空表中头结点的指针域为空),因此空表和非空表的处理也就得到统一。

 

单链表上基本操作的实现

1.采用头插法建立单链表

LinkList List_HeadInsert(LinkList& L) {    //逆向建立单链表
    LNode* s; int x;
    L = (LinkList)malloc(sizeof(LNode));//创建头结点
    L->next = NULL;                        //初始为空链表
    printf("输入x的值:");
    scanf("%d", &x);                    //输入结点的值
    while (x != 9999) {
        s = (LNode*)malloc(sizeof(LNode));    //创建新结点
        s->data = x;
        s->next = L->next;
        L->next = s;                    //将新结点插入表中,L为头指针
        printf("输入x的值:");
        scanf("%d", &x);
    }
    return L;
}

2.采用尾插法建立单链表

LinkList List_TailInsert(LinkList& L) {    //正向向建立单链表
    int x;
    L = (LinkList)malloc(sizeof(LNode));//创建头结点

    LNode* r = L;
    printf("输入x的值:");
    scanf("%d", &x);                    //输入结点的值
    while (x != 9999) {
        LNode* s = (LNode*)malloc(sizeof(LNode));    //创建新结点
        s->data = x;
        r->next = s;
        r = s;                            //r指向新的表位结点
        printf("输入x的值:");
        scanf("%d", &x);
    }
    r->next = NULL;                        //尾结点指针置空
    return L;
}

3.按位置查找

LNode* GetElem(LinkList L, int i) {
    int j = 1;            //计数,初始为1
    LNode* p = L->next;    //头结点指针赋值给p
    if (i == 0)
        return L;        //若i等于0,则返回头结点
    if (i < 1)
        return NULL;    //若i无效,则返回NULL
    while (p && j < i) {    //若从第1个结点开始找,查找第i个结点
        p = p->next;
        j++;
    }
    return p;
}

4.按值查找

void LocateElem(LinkList L, int e) {
    LNode* p = L->next;
    int i = 1;
    while (p && e != p->data) {
        p = p->next;
        i++;
    }
    if (p)
        printf("该节点的位置为:%d", i);
    else
        printf("为查找到此数值。");
}

5.插入结点(前插)

LNode* HInsertLNode(LinkList& L, LNode* s, int i) {
    LNode* p = GetElem(L, i - 1);
    s->next = p->next;
    p->next = s;
    return L;
}

6.插入结点(后插)

LNode* TInsertLNode(LinkList& L, LNode* s, int i) {
    LNode* p = GetElem(L, i);
    s->next = p->next;
    p->next = s;
    return L;
}

 7.删除结点(按位置)

LNode* DeleteLNode(LinkList& L, int i) {
    LNode* p = GetElem(L, i - 1);        //查找删除结点的位置
    LNode* q = p->next;                    //令q指向被删除的结点
    p->next = q->next;                    //将q指向结点从链中断开
    free(q);
    return p;
}

8.删除结点(按结点)

void DeleteLNodE(LNode* p) {
    LNode* q=p->next;                //创建q指向p的后继结点
    p->data = q->data;                //和后继节点交换数据
    p->next = q->next;                //将*q结点从链中删除
    free(p);                        //释放后继结点的存储空间
}

9.输出单链表

void Print(LinkList& L) {
    LNode* p = L->next;
    printf("输出链表:");
    while (p)
    {
        printf("%3d", p->data);
        p = p->next;
    }
}

 

上一篇:单链表


下一篇:2 单链表