数据结构_静态链表(C语言)

数据结构总目录

本章目录

  • (一)静态链表图文解析
  • (二)静态链表代码解析
    • 1. 基本操作
      • 1.1 存储结构
      • 1.2 初始化
      • 1.3 插入数据
      • 1.4 删除数据
      • 1.5 修改数据
    • 2. 源代码及测试
      • 2.1 源代码
      • 2.2 测试结果

(一)静态链表图文解析

静态链表结构

  • 静态链表的结构实际上就是一个数组,静态链表的数组中,每一个元素代表一个结点,结点同样和链表一样包括数据域和指针域
  • 只是在静态链表中的指针域不再是指针指向下一个结点的地址,而是用于存储下一个结点的数组下标,这样同样可以实现结点之间的连接关系

图示

在静态链表中

  • 指针域大于0,则代表下一个结点的数组下标
  • 指针域等于-1,则代表下一个结点为空
  • 指针域等于-2,则代表该结点尚未被使用
    数据结构_静态链表(C语言)_第1张图片
    数据结构_静态链表(C语言)_第2张图片

(二)静态链表代码解析

1. 基本操作

1.1 存储结构

#define MaxSize 10	//最大链表长度

typedef char DataType;	
typedef struct LNode
{
    DataType data;	//数据域
    int next;		//指针域
}StaticList;

1.2 初始化

void InitList(StaticList **L)
{
    // 为静态链表分配空间
    (*L) = (StaticList *)malloc(MaxSize * sizeof(StaticList));
    // 初始化头结点
    StaticList *s = *L;
    s[0].data = '\0';
    s[0].next = -1;
    // 初始化链表
    int i;
    for (i = 1; i < MaxSize; i++)
    {
        s[i].data = '\0';
        s[i].next = -2;
    }
    printf("已初始化链表\n");
}

1.3 插入数据

头部插入

void HeadInsert(StaticList *L)
{
    if (L)
    {
        DataType x;
        printf("请输入插入的数据:");
        fflush(stdin);
        scanf("%c", &x);
        // 获取新结点的下标位置
        int free_node = GetFreeNodeIndex(L);
        if (free_node > 0)
        {
            // 设置新结点的数据
            L[free_node].data = x;

            // 新结点指向链表的第一个结点
            L[free_node].next = L[0].next;

            // 头结点指向新结点,使得新结点成为链表的第一个结点
            L[0].next = free_node;

            printf("插入成功!\n");
        }
        else
        {
            printf("插入失败! 链表空间已满!\n");
        }       
    }
    else
    {
        printf("插入失败! 链表已销毁!\n");
    }
}

尾部插入

void TailInsert(StaticList *L)
{
    if (L)
    {
        int i;
        DataType x;
        printf("请输入插入的数据:");
        fflush(stdin);
        scanf("%c", &x);

        int free_node = GetFreeNodeIndex(L);
        if (free_node > 0)
        {
            int tail_index = 0;
            // 查找尾结点下标
            while (L[tail_index].next > 0)
            {
                tail_index = L[tail_index].next;
            }
            // 设置新结点数据
            L[free_node].data = x;

            // 新结点指针域设置为空
            L[free_node].next = -1;

            //尾结点指向新结点,使得新结点成为链表的最后一个结点
            L[tail_index].next = free_node;

            printf("插入成功!\n");
        }
        else
        {
            printf("插入失败! 链表空间已满\n");
        }
    }
    else
    {
        printf("插入失败! 链表已销毁!\n");
    }
}

按位置插入

void LocateInsert(StaticList *L)
{
    if (L)
    {
        int i, k;
        DataType x;
        printf("请输入插入的数据和插入位置:");
        scanf("%d %c", &k, &x);

        int free_node = GetFreeNodeIndex(L);
        if (k > 0 && free_node > 0)
        {
            int insert_index = 0;
            
            // 查找链表中第(k-1)个结点
            while((--k) && L[insert_index].next > 0)
            {   
                insert_index = L[insert_index].next;
            }
            // 插入新结点
            if (k == 0)
            {
                // 设置新结点数据
                L[free_node].data = x;
                
                // 新结点指向第k个结点下标
                L[free_node].next = L[insert_index].next;

                // 第(k-1)个结点指向新结点
                L[insert_index].next = free_node;
                
                printf("插入成功!\n");
            }
            else
            {
                printf("插入失败! 插入位置不合法!\n");
            }
        }
        else
        {
            printf("插入失败! 插入位置不合法/链表空间已满!\n");
        }
    }
    else
    {
        printf("插入失败! 链表已销毁!\n");
    }
}

1.4 删除数据

头部删除

void HeadDelete(StaticList *L)
{
    if (L)
    {
        if (L[0].next > 0)
        {
            int first_index;
            // 获取第一个结点
            first_index = L[0].next;

            // 头结点指向第二个结点
            L[0].next = L[first_index].next;

            // 初始化第一个结点
            L[first_index].data = '\0';
            L[first_index].next = -2;

            printf("删除成功!\n");
        }
        else
        {
            printf("删除失败! 链表为空!\n");
        }
    }
    else
    {
        printf("删除失败! 链表已销毁!\n");
    }
}

尾部删除

// 尾部删除
void TailDelete(StaticList *L)
{
    if (L)
    {
        if (L[0].next > 0)
        {
            int i = 0, j = 0;
            // 查询倒数第一个结点(i)和倒数第二个结点(j)
            while (L[i].next > 0)
            {
                j = i;
                i = L[i].next;
            }
            // 倒数第二个结点指向-1
            L[j].next = -1;
            
            // 初始化最后一个结点
            L[i].data = '\0';
            L[i].next = -2;
            
            printf("删除成功!\n");
        }
        else
        {
            printf("插入失败! 链表为空!\n");
        }
    }
    else
    {
        printf("插入失败! 链表已销毁!\n");
    }
}

按位置删除

// 按位置删除
void LocateDelete(StaticList *L)
{
    if (L)
    {
        int k;
        printf("请输入删除的数据位置:");
        scanf("%d", &k);

        if (k > 0 && L[0].next > 0)
        {
            int i = 0, j = 0;
            // 查询第(j = k-1)个结点和第(i = k)个结点
            while ((k--) && L[i].next > 0)
            {
                j = i;
                i = L[i].next;
            }
            if (k < 0)
            {
                // 第(k-1)个结点指向第(k+1)个结点
                L[j].next = L[i].next;
                
                // 初始化第k个结点
                L[i].data = '\0';
                L[i].next = -2;

                printf("删除成功!\n");
            }
            else
            {
                printf("删除失败! 删除位置不合法!\n");
            }        
        }
        else
        {
            printf("删除失败! 链表为空!\n");
        }
    }
    else
    {
        printf("删除失败! 链表已销毁!\n");
    }
}

1.5 修改数据

// 修改链表
void ListModify(StaticList *L)
{
    if (L)
    {
        int k;
        DataType x;
        printf("请输入需要修改的位置和修改后的数据:");
        scanf("%d %c", &k, &x);

        if (k > 0)
        { 
            int index = 0;
            // 查询第i个结点位置
            while ((k--) && L[index].next > 0)
            {
                index = L[index].next;
            } 
            if (k < 0)
            {
                L[index].data = x;
                printf("修改成功!\n");
            }
            else
            {
                printf("修改失败! 修改位置不合法!\n");
            }
        }
        else
        {
            printf("修改失败! 修改位置不合法!\n");
        }
    }
    else
    {
        printf("链表已销毁!\n");
    }
}

2. 源代码及测试

2.1 源代码

#include
#include

#define MaxSize 10

typedef char DataType;
typedef struct LNode
{
    DataType data;
    int next;
}StaticList;

void InitList(StaticList **L)
{
    // 为静态链表分配空间
    (*L) = (StaticList *)malloc(MaxSize * sizeof(StaticList));
    // 初始化
    StaticList *s = *L;
    s[0].data = '\0';
    s[0].next = -1;

    int i;
    for (i = 1; i < MaxSize; i++)
    {
        s[i].data = '\0';
        s[i].next = -2;
    }
    printf("已初始化链表\n");
}

// 查找空闲结点位置的下标
int GetFreeNodeIndex(StaticList *L)
{
    int i;
    for (i = 1; i < MaxSize; i++)
    {        
        if (L[i].next == -2)
        {
            return i;
        }
    }
    return 0;
}

// 头部插入
void HeadInsert(StaticList *L)
{
    if (L)
    {
        DataType x;

        printf("请输入插入的数据:");
        fflush(stdin);
        scanf("%c", &x);

        // 获取新结点的下标位置
        int free_node = GetFreeNodeIndex(L);

        if (free_node > 0)
        {
            // 设置新结点的数据
            L[free_node].data = x;

            // 新结点指向链表的第一个结点
            L[free_node].next = L[0].next;

            // 头结点指向新结点,使得新结点成为链表的第一个结点
            L[0].next = free_node;

            printf("插入成功!\n");
        }
        else
        {
            printf("插入失败! 链表空间已满!\n");
        }       
    }
    else
    {
        printf("插入失败! 链表已销毁!\n");
    }
}

// 尾部插入
void TailInsert(StaticList *L)
{
    if (L)
    {
        int i;
        DataType x;

        printf("请输入插入的数据:");
        fflush(stdin);
        scanf("%c", &x);

        int free_node = GetFreeNodeIndex(L);

        if (free_node > 0)
        {
            int tail_index = 0;
            // 查找尾结点下标
            while (L[tail_index].next > 0)
            {
                tail_index = L[tail_index].next;
            }
            // 设置新结点数据
            L[free_node].data = x;

            // 新结点指针域设置为空
            L[free_node].next = -1;

            //尾结点指向新结点,使得新结点成为链表的最后一个结点
            L[tail_index].next = free_node;

            printf("插入成功!\n");
        }
        else
        {
            printf("插入失败! 链表空间已满\n");
        }
    }
    else
    {
        printf("插入失败! 链表已销毁!\n");
    }
}

// 按位置插入
void LocateInsert(StaticList *L)
{
    if (L)
    {
        int i, k;
        DataType x;

        printf("请输入插入的数据和插入位置:");
        scanf("%d %c", &k, &x);

        int free_node = GetFreeNodeIndex(L);

        if (k > 0 && free_node > 0)
        {
            int insert_index = 0;
            
            // 查找链表中第(k-1)个结点
            while((--k) && L[insert_index].next > 0)
            {   
                insert_index = L[insert_index].next;
            }
            // 插入新结点
            if (k == 0)
            {
                // 设置新结点数据
                L[free_node].data = x;
                
                // 新结点指向第k个结点下标
                L[free_node].next = L[insert_index].next;

                // 第(k-1)个结点指向新结点
                L[insert_index].next = free_node;
                
                printf("插入成功!\n");
            }
            else
            {
                printf("插入失败! 插入位置不合法!\n");
            }
        }
        else
        {
            printf("插入失败! 插入位置不合法/链表空间已满!\n");
        }
    }
    else
    {
        printf("插入失败! 链表已销毁!\n");
    }
}

// 头部删除
void HeadDelete(StaticList *L)
{
    if (L)
    {
        if (L[0].next > 0)
        {
            int first_index;

            // 获取第一个结点
            first_index = L[0].next;

            // 头结点指向第二个结点
            L[0].next = L[first_index].next;

            // 初始化第一个结点
            L[first_index].data = '\0';
            L[first_index].next = -2;

            printf("删除成功!\n");
        }
        else
        {
            printf("删除失败! 链表为空!\n");
        }
    }
    else
    {
        printf("删除失败! 链表已销毁!\n");
    }
}

// 尾部删除
void TailDelete(StaticList *L)
{
    if (L)
    {
        if (L[0].next > 0)
        {
            int i = 0, j = 0;
            // 查询倒数第一个结点(i)和倒数第二个结点(j)
            while (L[i].next > 0)
            {
                j = i;
                i = L[i].next;
            }
            // 倒数第二个结点指向-1
            L[j].next = -1;
            
            // 初始化最后一个结点
            L[i].data = '\0';
            L[i].next = -2;
            
            printf("删除成功!\n");
        }
        else
        {
            printf("插入失败! 链表为空!\n");
        }
    }
    else
    {
        printf("插入失败! 链表已销毁!\n");
    }
}

// 按位置删除
void LocateDelete(StaticList *L)
{
    if (L)
    {
        int k;

        printf("请输入删除的数据位置:");
        scanf("%d", &k);

        if (k > 0 && L[0].next > 0)
        {
            int i = 0, j = 0;
            // 查询第(j = k-1)个结点和第(i = k)个结点
            while ((k--) && L[i].next > 0)
            {
                j = i;
                i = L[i].next;
            }
            if (k < 0)
            {
                // 第(k-1)个结点指向第(k+1)个结点
                L[j].next = L[i].next;
                
                // 初始化第k个结点
                L[i].data = '\0';
                L[i].next = -2;

                printf("删除成功!\n");
            }
            else
            {
                printf("删除失败! 删除位置不合法!\n");
            }        
        }
        else
        {
            printf("删除失败! 链表为空!\n");
        }
    }
    else
    {
        printf("删除失败! 链表已销毁!\n");
    }
}

// 修改链表
void ListModify(StaticList *L)
{
    if (L)
    {
        int k;
        DataType x;

        printf("请输入需要修改的位置和修改后的数据:");
        scanf("%d %c", &k, &x);

        if (k > 0)
        { 
            int index = 0;
            // 查询第i个结点位置
            while ((k--) && L[index].next > 0)
            {
                index = L[index].next;
            } 
            if (k < 0)
            {
                L[index].data = x;
                printf("修改成功!\n");
            }
            else
            {
                printf("修改失败! 修改位置不合法!\n");
            }
        }
        else
        {
            printf("修改失败! 修改位置不合法!\n");
        }
    }
    else
    {
        printf("链表已销毁!\n");
    }
}

// 遍历链表
void DisplayList(StaticList *L)
{
    if (L)
    {
        if (L[0].next > 0)
        {
            int index = L[0].next;
            while(index > 0)
            {
                printf("%c->", L[index].data);
                index = L[index].next;
            }
            printf("null\n");
        }
        else
        {
            printf("链表为空!\n");
        }    
    }
    else
    {
        printf("遍历失败! 链表已销毁!\n");
    }
}

// 求链表长度
void ListLength(StaticList *L)
{
    if (L)
    {
        int index = 0, length = 0;
        while (L[index].next > 0)
        {
            length++;
            index = L[index].next;
        }
        printf("链表长度length = %d\n", length);
    }
    else
    {
        printf("链表已销毁!\n");
    }
}

// 判断链表是否为空
void ListEmpty(StaticList *L)
{
    if (L)
    {
        if (L[0].next > 0)
        {
            printf("链表非空!\n");
        }
        else
        {
            printf("链表为空!\n");
        }
    }
    else
    {
        printf("链表已销毁!\n");
    }
}

// 清空链表
void ClearList(StaticList *L)
{
    if (L)
    {
        if (L[0].next > 0)
        {
            int i = L[0].next, j = L[0].next;
            // 依次清除结点
            while (i > 0)
            {
                // j:用于暂存下一个结点
                j = L[i].next;

                // 初始化结点i
                L[i].next = -2;
                
                // i:移动到下一个结点
                i = j;
            }
            L[0].next = -1;
            printf("链表已清空!\n");
        }
        else
        {
            printf("链表为空!\n");
        }   
    }
    else
    {
        printf("链表已销毁!\n");
    }
}

// 销毁链表
void DestroyList(StaticList **L)
{
    free(*L);
    (*L) = NULL;
    printf("链表已销毁!\n");
}

// 打印静态链表数组
void DisplayArr(StaticList *L)
{
    if (L)
    {   
        int i;
        printf("***************************\n");
        printf("下标:\t");
        for (i = 0; i < MaxSize; i++)
        {
            printf("%d\t", i);        
        }
        printf("\n数据域:\t");
        for (i = 0; i < MaxSize; i++)
        {
            if (L[i].data)
            {
                printf("%c\t", L[i].data);
            }
            else
            {
                printf("-\t");
            }
        }
        printf("\n指针域:\t");
        for (i = 0; i < MaxSize; i++)
        {
            printf("%d\t", L[i].next);
            
        }
        printf("\n***************************\n");
    }
    else
    {
        printf("链表已销毁!\n");
    }
}

int main()
{
    printf("*********************************\n");
	printf("其他 | 0:退出\t1:初始化\n");
	printf("插入 | 2:头插\t3:尾插\t4:按位插\n");
	printf("删除 | 5:头删\t6:尾删\t7:按位删\n");
    printf("查询 | 8:修改\t9:遍历\t10:求表长\n");
    printf("其他 | 11:表空\t12:清空\t13:销毁\n");
    printf("测试 | 14:打印静态链表数组\n");
    printf("*********************************\n");
	
	int k;
	StaticList *L;
    InitList(&L);
    while (1)
    {
        printf("请输入操作序号:");
        scanf("%d", &k);
		if (!k)
		{
			break;
		}
        switch (k)
        {
            case 1:InitList(&L);    break;
            // 插入
            case 2:HeadInsert(L);	break;
            case 3:TailInsert(L);	break;
            case 4:LocateInsert(L); break;
            // 删除
            case 5:HeadDelete(L);	break;
            case 6:TailDelete(L);	break;
            case 7:LocateDelete(L);	break;
            // 查询
            case 8:ListModify(L);	break;
            case 9:DisplayList(L);	break;
            case 10:ListLength(L);	break;
            // 其他
            case 11:ListEmpty(L);	break;
            case 12:ClearList(L);	break;
            case 13:DestroyList(&L);break;
            case 14:DisplayArr(L);  break;
            default:break;
        }
        printf("\n");
	}
    system("pause");
    return 0;
}

2.2 测试结果

数据结构_静态链表(C语言)_第3张图片
数据结构_静态链表(C语言)_第4张图片

你可能感兴趣的:(#,线性表,数据结构,C语言,静态链表)