C语言 数据结构 线性表的链式表示和实现

数据结构课程设计专栏指路

数据结构课程设计(C语言版)
包括顺序表、链表、栈、循环队列、二叉树、图

线性表的链式表示和实现

1 链表结构

链表由一个一个结点通过指针链接而成。
每个结点分为数据域与指针域
链表可以定义一个头结点,不储存数据,也可以没有头结点
该篇的链表是有头结点的

typedef struct node //typedef 用于取别名
{
    ElemType data;
    struct node *next;
} * PNODE, NODE; //PNODE 就是 struct node *,NODE就是struct node

2 基本操作函数

  1. 初始化单链表
    产生一个头结点,返回指向头结点的头指针
PNODE InitList()
{
    PNODE temp;                         //定义一个结构体指针
    temp = (PNODE)malloc(sizeof(NODE)); //定义一个头节点
    temp->next = NULL;                  //头结点不储存数据,头结点的指针域暂时为空
    return temp;
}
  1. 清除单链表
    传入链表头指针,依次调用free()清除
void ListClear(PNODE head)
{
    PNODE p = head, temp;
    while (p != NULL)
    {
        temp = p->next;//用temp存下一个地址
        free(p);
        p = temp;
    }
}
  1. 求单链表长度
    传入链表头指针,依次遍历,用变量i统计
int ListLength(PNODE head)
{
    int i = 0;
    PNODE p = head->next;
    while (p != NULL)
    {
        i++;
        p = p->next;
    }
    return i;
}
  1. 判断单链表是否为空表
    定义枚举类型bool,其中false=0,true=1。
typedef enum
{
    false,
    true
} bool;

传入链表头指针,若长度=0,返回true(1),说明确实是空链表。反之长度不为0,返回false(0),说明链表不空。

bool ListIsEmpty(PNODE head)
{
    return !ListLength(head);
}
  1. 取单链表第pos位置上的元素
ElemType ListGetData(PNODE head, int pos)
{
    PNODE p = head;

    //pos超过长度时报错
    if (ListLength(head) < pos)
    {
        printf("pos超过最大长度\n");
        return p->next->data;
    }

    for (int i = 0; i < pos; i++)
    {
        p = p->next;
    }

    return p->data;
}
  1. 打印单链表(遍历)
void ListPrint(PNODE head)
{
    printf("链表:");

    PNODE p = head->next; //定义p指向首元节点(不是头结点)
    while (p != NULL)     //直到p==NULL,遍历完了才结束
    {
        printf("%d->", p->data); //打印节点里的数据
        p = p->next;             //指针移动指向下一个节点
    }
    printf("NULL\n");
}
  1. 向单链表插入一个元素
bool ListInsertList(PNODE head, ElemType item, int pos)
{

    if (ListLength(head) + 1 < pos)
    {
        printf("pos超过最大长度+1\n");
        return false;
    }

    //开辟一小块内存用于存放数据
    PNODE temp, p = head;
    temp = (PNODE)malloc(sizeof(NODE));
    temp->data = item;

    //找到第(pos-1)个结点,让p指向它
    for (int i = 0; i < pos - 1; i++)
    {
        p = p->next;
    }

    //插入
    temp->next = p->next;
    p->next = temp;

    return true;
}
  1. 在单链表中删除一元素
bool ListDeleteList(PNODE head, int pos)
{
    PNODE p = head;

    if (ListLength(head) + 1 < pos)
    {
        printf("pos超过最大长度+1\n");
        return false;
    }

    //找到第(pos-1)个结点,让p指向它
    for (int i = 0; i < pos - 1; i++)
    {
        p = p->next;
    }

    //让pos-1个结点直接指向pos+1个结点
    p->next = p->next->next;

    free(p->next);
    return true;
}

3 整体代码

该程序分为两个文件,“LinkList.h"与"test2.c”
将数据结构类型定义(typedef)部分与基础操作函数放在头文件LinkList.h
主函数以及其他部分放在test2.c

test2.c

  • 为检验代码可行性,设计main()函数验证
  • 功能:
    • 接收元素组成链表,打印链表,计算长度
    • 删除第三个链表元素,再次打印链表,计算长度
#include <stdio.h>
#include <stdlib.h>

typedef int ElemType;   //定义数据类型

#include "LinkList.h"  //调用头文件

int main()
{
    PNODE head =InitList(); //接受InitList()的返回值,即head指向了一个头结点

    ElemType x;
    int i = 1;

    printf("输入:");
    scanf("%d", &x);
    while (x != -1)
    {
        if (ListInsertList(head, x, i) == 0)
        {
            return 0;
        }
        i++;
        scanf("%d", &x);
    }


    ListPrint(head);
    printf("%d\n", ListLength(head));

    printf("第三个元素是:%d\n", ListGetData(head, 3));
    ListDeleteList(head,3);

    ListPrint(head);
    printf("%d\n", ListLength(head));

    return 0;
}

LinkList.h

typedef enum
{
    false,
    true
} bool;

typedef struct node //typedef 用于取别名
{
    ElemType data;
    struct node *next;
} * PNODE, NODE; //PNODE 就是 struct node *,NODE就是struct node

//初始化单链表
PNODE InitList()
{
    PNODE temp;                         //定义一个结构体指针
    temp = (PNODE)malloc(sizeof(NODE)); //定义一个头节点
    temp->next = NULL;                  //头结点不储存数据,头结点的指针域暂时为空
    return temp;
}

//清除单链表
void ListClear(PNODE head)
{
    PNODE p = head, temp;
    while (p != NULL)
    {
        temp = p->next;
        free(p);
        p = temp;
    }
}

//求单链表长度
int ListLength(PNODE head)
{
    int i = 0;
    PNODE p = head->next;
    while (p != NULL)
    {
        i++;
        p = p->next;
    }
    return i;
}

//判断单链表是否为空表
bool ListIsEmpty(PNODE head)
{
    return !ListLength(head);
}

//取单链表第pos位置上的元素
ElemType ListGetData(PNODE head, int pos)
{
    PNODE p = head;

    //pos超过长度时报错
    if (ListLength(head) < pos)
    {
        printf("pos超过最大长度\n");
        return p->next->data;
    }

    for (int i = 0; i < pos; i++)
    {
        p = p->next;
    }

    return p->data;
}

//打印单链表(遍历)
void ListPrint(PNODE head)
{
    printf("链表:");

    PNODE p = head->next; //定义p指向首元节点(不是头结点)
    while (p != NULL)     //直到p==NULL,遍历完了才结束
    {
        printf("%d->", p->data); //打印节点里的数据
        p = p->next;             //指针移动指向下一个节点
    }
    printf("NULL\n");
}

//向单链表插入一个元素
bool ListInsertList(PNODE head, ElemType item, int pos)
{

    if (ListLength(head) + 1 < pos)
    {
        printf("pos超过最大长度+1\n");
        return false;
    }

    //开辟一小块内存用于存放数据
    PNODE temp, p = head;
    temp = (PNODE)malloc(sizeof(NODE));
    temp->data = item;

    //找到第(pos-1)个结点,让p指向它
    for (int i = 0; i < pos - 1; i++)
    {
        p = p->next;
    }

    //插入
    temp->next = p->next;
    p->next = temp;

    return true;
}

bool ListDeleteList(PNODE head, int pos)
{
    PNODE p = head;

    if (ListLength(head) + 1 < pos)
    {
        printf("pos超过最大长度+1\n");
        return false;
    }

    //找到第(pos-1)个结点,让p指向它
    for (int i = 0; i < pos - 1; i++)
    {
        p = p->next;
    }

    //让pos-1个结点直接指向pos+1个结点
    p->next = p->next->next;

    free(p->next);
    return true;
}


4 运行结果

在这里插入图片描述

5 附加题

  • 合并两个有序链表
  • 编写一个函数void ListMergeListPlus(PNODE La, PNODE Lb, PNODE Lc),实现将两个有序单链表La和 Lb合并成一个新的有序单链表Lc,同时销毁原有单链表La和Lb。要求把该函数添加到文件LinkList.h中,并在主函数文件test2.c中添加相应语句进行测试。
  • 步骤:
    • 刚开始先定义pa、pb指向La、Lb首元结点,pc 指向Lc头结点
    • pa、pb都存在时就依次比较,谁小,就加入Lc(变成pc指向结点的next域),同时pa/pb指向链表La/pb下一个,pc也指向链表Lc下一个
    • 最后可能存在有剩余的情况(La全添入Lc,Lb还没有或者Lb全添入Lc,La还没有),只要修改pc->next就行
  • 添入LinkList.h
void ListMergeListPlus(PNODE La, PNODE Lb, PNODE Lc)
{
    //让pa指向La首元结点(头结点后一个)
    PNODE pa = La->next;
    PNODE pb = Lb->next;
    PNODE pc = Lc;

    //pa pb两个都存在就能继续
    while (pa && pb)
    {
        if (pa->data < pb->data)
        {
            pc->next = pa;
            pa = pa->next;
            pc = pc->next;
        }
        else
        {
            pc->next = pb;
            pb = pb->next;
            pc = pc->next;
        }   
    }

    if(pa)
    {
        pc->next = pa;
    }
    if(pb)
    {
        pc->next = pb;
    }

}
  • 主函数
    • 修改test2.c
    • 输入a链表与b链表
    • 合并为c链表
    • 打印c链表
#include <stdio.h>
#include <stdlib.h>

typedef int ElemType;

#include "LinkList.h"

int main()
{
    PNODE heada= InitList(),headb= InitList(),headc = InitList();//接受InitList()的返回值,即head指向了一个头结点

    ElemType x;
    int i = 1;

    printf("输入a:");
    scanf("%d", &x);
    while (x != -1)
    {
        if (ListInsertList(heada, x, i) == 0)
        {
            return 0;
        }
        i++;
        scanf("%d", &x);
    }

    i = 1;  //重置i
    printf("输入b:");
    scanf("%d", &x);
    while (x != -1)
    {
        if (ListInsertList(headb, x, i) == 0)
        {
            return 0;
        }
        i++;
        scanf("%d", &x);
    }
    
    
    ListMergeListPlus(heada,headb,headc);
    ListPrint(headc);

    return 0;
}


  • 注意:输入的两个链表要是有序链表

  • 运行结果
    在这里插入图片描述

好的,我可以为您提供一份栈的链式表示实现C语言实验报告。 实验目的:了解栈的链式表示实现过程,掌握链表的基本操作。 实验内容:设计一个栈的链式存储结构,并实现入栈、出栈等基本操作。 实验步骤: 1. 定义结构体,包括存储数据的成员和指向下一个节点的指针成员。 ``` typedef struct node { int data; struct node *next; } Node; ``` 2. 定义栈顶指针,并初始化为空。 ``` Node *top = NULL; ``` 3. 实现入栈操作,即在链表头部插入节点。 ``` void push(int value) { Node *new_node = (Node *) malloc(sizeof(Node)); new_node->data = value; new_node->next = top; top = new_node; } ``` 4. 实现出栈操作,即删除链表头部节点。 ``` int pop() { if (top == NULL) { printf("Stack is empty.\n"); return -1; } int value = top->data; Node *temp = top; top = top->next; free(temp); return value; } ``` 5. 实现打印栈中元素的操作。 ``` void print_stack() { if (top == NULL) { printf("Stack is empty.\n"); return; } Node *current = top; printf("Stack: "); while (current != NULL) { printf("%d ", current->data); current = current->next; } printf("\n"); } ``` 6. 在主函数中调用上述操作,测试栈的功能。 ``` int main() { push(1); push(2); push(3); print_stack(); // output: Stack: 3 2 1 pop(); print_stack(); // output: Stack: 2 1 push(4); print_stack(); // output: Stack: 4 2 1 return 0; } ``` 实验结果:成功实现了栈的链式存储结构,并实现了入栈、出栈和打印栈中元素的基本操作。 以上就是栈的链式表示实现C语言实验报告,希望对您有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丸丸丸子w

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值