bilibiliclass22-28_数据结构与算法_线性表的链式表示和实现

知识回顾

顺序表的特点:以物理位置相邻表示逻辑关系。

顺序表的优点:任一元素均可随机存取。

顺序表的缺点:进行插入和删除操作时,需移动大量的元素。存储空间不灵活

 

链式存储结构

结点在存储器中的位置是任意的,即逻辑上相邻的数据元素在物理上不一定相邻

这组存储单元既可以是连续的,也可以是不连续的,甚至是零散分布在内存中的任意位置上的。

例子1

线性表:(赵,钱,孙,李,周,吴,郑,王)

bilibiliclass22-28_数据结构与算法_线性表的链式表示和实现_第1张图片bilibiliclass22-28_数据结构与算法_线性表的链式表示和实现_第2张图片

bilibiliclass22-28_数据结构与算法_线性表的链式表示和实现_第3张图片

例子2

例:26个英文小写字母表的链式存储结构
逻辑结构:( a, b,... ,y,z)

bilibiliclass22-28_数据结构与算法_线性表的链式表示和实现_第4张图片

与链式存储有关的术语

1、结点:数据元素的存储映象。由数据域和指针域两部分组成

数据域:存储元素数值数据
指针域:存储直接后继结点的存储位置

2、链表:n个结点由指针链组成一个链表。

 

单链表、双链表、循环链表:

结点只有一个指针域的链表,称为单链表或线性链表

单链表是由头指针唯一确定,因此单链表可以用头指针的名字来命名。

bilibiliclass22-28_数据结构与算法_线性表的链式表示和实现_第5张图片
结点有两个指针域的链表,称为L为双链表

bilibiliclass22-28_数据结构与算法_线性表的链式表示和实现_第6张图片
首尾相接的链表称为循环链表

bilibiliclass22-28_数据结构与算法_线性表的链式表示和实现_第7张图片

头指针 头结点 首元结点


头指针:是指向链表中第一个结点的指针

首元结点:是指链表中存储第一个数据元素a1的结点

头结点:是在链表的首元结点之前附设的一个结点;

bilibiliclass22-28_数据结构与算法_线性表的链式表示和实现_第8张图片

前面的例子中的链表的存储结构示意图有以下两种形式:

①不带头结点

bilibiliclass22-28_数据结构与算法_线性表的链式表示和实现_第9张图片
②带头结点

bilibiliclass22-28_数据结构与算法_线性表的链式表示和实现_第10张图片

头结点好处

1便于首元结点的处理
首元结点的地址保存在头结点的指针域中,所以在链表的第一个位置上的操作和其它位置一致,无须进行特殊处理;
2便于空表和非空表的统一处理
无论链表是否为空,头指针都是指向头结点的非空指针,因此空表和非空表的处理也就统一了。

3.头结点的数据域可以为空,也可存放线性表长度等附加信息,但此结点不能计入链表长度值
bilibiliclass22-28_数据结构与算法_线性表的链式表示和实现_第11张图片

 

空表

无头结点时,头指针为空时表示空表

bilibiliclass22-28_数据结构与算法_线性表的链式表示和实现_第12张图片bilibiliclass22-28_数据结构与算法_线性表的链式表示和实现_第13张图片

有头结点时,当头结点的指针域为空时表示空表

bilibiliclass22-28_数据结构与算法_线性表的链式表示和实现_第14张图片bilibiliclass22-28_数据结构与算法_线性表的链式表示和实现_第15张图片

 

链表(链式存储结构)的特点

(1)结点在存储器中的位置是任意的,即逻辑上相邻的数据元素在物理上不一定相邻。
(2)访问时只能通过头指针进入链表,并通过每个结点的指针域依次向后顺序扫描其余结点,所以寻找第一个结点和最后一个结点所花费的时间不等

 

知识回顾

线性表的链式存储结构
线性表中数据元素(结点)在存储器中的位置是任意的,即逻辑上相邻的数据元素在物理位置上不一定相邻。
结点
数据│指针
链表  n个结点由指针链组成一个链表。链表是顺序存取的。
单链表:每个结点只有一个指针域
双链表:每个结点有两个指针域

循环链表:链表结点首尾相接

 

单链表基本操作的实现

#define _CRT_SECURE_NO_WARNINGS
#include 
#include 

//链表的数据域
struct student
{
    char name[20];
    int num;
};


//链表的样子
struct Node {
    struct student data;
    struct Node* next;
};

//创建表头,即单链表的初始化
struct Node* creatList()
{
    struct Node* headNode = (struct Node*)malloc(sizeof(struct Node));
    //headNode 成为了结构体变量
    //headNode->next=1;
    headNode->next = NULL;
    return headNode;
}

//创建节点
struct Node* creatNode(struct student data)
{
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = data;
    newNode->next = NULL;
    return newNode;
}

//打印节点,遍历节点
void printList(struct Node* headNode)
{
    struct Node* pMove = headNode->next;
    printf("name\tnum\n");
    while (pMove)
    {
        printf("%s\t%d\n",pMove->data.name, pMove->data.num);
        pMove = pMove->next;
    }
    printf("\n");
}


//表头法插入
void insertNodeByHead(struct Node* headNode, struct student data)
{
    //1.创建插入的结点
    struct Node* newNode = creatNode(data);
    newNode->next = headNode->next;
    headNode->next = newNode;
}

//链表的删除:指定位置的删除
void deleteNodeByAppoinNum(struct Node* headNode, int num)
{
    struct Node* posNode = headNode->next;
    struct Node* posNodeFront = headNode;
    if (posNode == NULL)
        printf("无法删除,链表为空\n");
    else
    {
        while (posNode->data.num != num)
        {
            posNodeFront = posNode;
            posNode = posNodeFront->next;
            if (posNode == NULL)
            {
                printf("没有找到相关信息,无法删除\n");
                return;
            }
        }
        posNodeFront->next = posNode->next;
        free(posNode);
    }
}

//判断链表是否为空
//空表:链表中无元素,称为空链表(头指针和头结点仍然在)
//若L为空表,则返回1,否则返回0
int ListEmpty(struct Node* list) 
{
    if (list->next)//非空
        return 0;
    else
        return 1;
}


//销毁单链表
void DestroyList_L(struct Node* list) 
{
    struct Node* p;
    while (list)
    {
        p = list;
        list = list->next;
        free(p);
    }
    return 1;
}

//清空链表:链表-->空表
void ClearList(struct Node* list)
{
    struct Node* p,*q;
    p = list->next;
    while (p)//没有到表尾
    {
        q = p->next;
        free(p);
        p = q;
    }
    //头指针设置为空
    list->next = NULL;
    return 1;
}

//求单链表的表长
int countList(struct Node* list)
{
    struct Node* p = list->next;//p指向第一个节点
    int count = 0;
    while (p!=NULL)//遍历
    {
        p = p->next;
        count++;
    }
    return count;
}


int main()
{
    struct Node* list = creatList();
    struct student info;
    while (1)
    {
        printf("请输入学生的姓名 学号:>");
        setbuf(stdin, NULL);
        scanf("%s%d",&info.name,&info.num);
        insertNodeByHead(list,info);
        printf("continue(Y/N)");
        setbuf(stdin,NULL);
        int choice = getchar();
        if (choice == 'N' || choice == 'n')
        {
            break;
        }
    }
    printList(list);
    printf("请输入要删除学生的学号:>");
    scanf("%d", &info.num);
    deleteNodeByAppoinNum(list, info.num);
    printList(list);
    ClearList(list);
    printList(list);
    return 0;
}

 

 

你可能感兴趣的:(bilibiliclass22-28_数据结构与算法_线性表的链式表示和实现)