C语言数据结构之顺序表和单链表

yizhihongxing

C语言数据结构之顺序表和单链表

1. 顺序表

1.1 顺序表的定义

顺序表是一种线性表结构,它的物理存储结构是数组,其数据元素存储在连续的存储单元中。在顺序表中,元素的排列顺序是固定的,元素间的逻辑关系是通过它们在数组中的下标关系进行描述的。

下面是顺序表的定义:

#define MAXSIZE 100    // 顺序表的最大长度

typedef struct {
    int data[MAXSIZE];    // 存储顺序表元素的数组
    int length;           // 当前顺序表的长度
} SqList;

1.2 常见操作

常见的操作有:插入、删除、查找、遍历。

下面是这些操作的代码实现:

插入

插入元素,需要先判断顺序表当前长度是否已经达到了最大长度,如果已经达到最大长度,则不允许插入元素。

bool ListInsert(SqList *L, int i, int e) {
    if (i < 1 || i > L->length + 1) {
        return false;    // 插入位置不合法
    }
    if (L->length >= MAXSIZE) {
        return false;    // 顺序表已满,无法插入元素
    }
    for (int j = L->length; j >= i; j--) {
        L->data[j] = L->data[j-1];
    }
    L->data[i-1] = e;
    L->length++;
    return true;
}

删除

删除元素,需要先判断要删除的位置是否合法,如果不合法,则不允许删除元素。

bool ListDelete(SqList *L, int i, int *e) {
    if (i < 1 || i > L->length) {
        return false;    // 删除位置不合法
    }
    *e = L->data[i-1];
    for (int j = i; j < L->length; j++) {
        L->data[j-1] = L->data[j];
    }
    L->length--;
    return true;
}

查找

查找元素,需要遍历整个顺序表,逐个与待查找元素进行比较。

int LocateElem(SqList L, int e) {
    for (int i = 0; i < L.length; i++) {
        if (L.data[i] == e) {
            return i+1;    // 返回元素在顺序表中的位置
        }
    }
    return 0;    // 未找到返回0
}

遍历

遍历元素,需要逐个输出顺序表中的元素。

void PrintList(SqList L) {
    for (int i = 0; i < L.length; i++) {
        printf("%d ", L.data[i]);
    }
    printf("\n");
}

1.3 示例说明

下面是一条示例说明:如何用顺序表实现两个有序数组的合并。

假设有两个有序数组A和B,长度分别为m和n,将它们合并成一个有序数组C。

#include <stdio.h>

#define MAXSIZE 100

typedef struct {
    int data[MAXSIZE];
    int length;
} SqList;

void Merge(SqList A, SqList B, SqList *C) {
    int i = 0, j = 0, k = 0;
    while (i < A.length && j < B.length) {
        if (A.data[i] < B.data[j]) {
            C->data[k++] = A.data[i++];
        } else {
            C->data[k++] = B.data[j++];
        }
    }
    while (i < A.length) {
        C->data[k++] = A.data[i++];
    }
    while (j < B.length) {
        C->data[k++] = B.data[j++];
    }
    C->length = k;
}

int main() {
    SqList A = {{1, 3, 5, 7}, 4};
    SqList B = {{2, 4, 6, 8}, 4};
    SqList C;
    Merge(A, B, &C);
    for (int i = 0; i < C.length; i++) {
        printf("%d ", C.data[i]);
    }
    printf("\n");
    return 0;
}

2. 单链表

2.1 单链表的定义

单链表是一种链式存储结构,它的每个结点都包含两部分,一部分是数据域,另一部分是指针域。指针域指向链表中下一个结点的地址,通过指针域,将所有结点连接起来,形成一个单链表。

下面是单链表的定义:

typedef struct LNode {
    int data;            // 数据域
    struct LNode *next;  // 指针域
} LNode, *LinkList;

2.2 常见操作

常见的操作有:插入、删除、查找、遍历。

下面的代码实现中,省略了一些边界判断,读者可以自行添加。

插入

在单链表中插入结点,需要先找到插入位置,然后将新结点插入到该位置之后。

bool ListInsert(LinkList *L, int i, int e) {
    LNode *p = *L;
    while (--i) {
        p = p->next;
    }
    LNode *s = (LNode *)malloc(sizeof(LNode));
    s->data = e;
    s->next = p->next;
    p->next = s;
    return true;
}

删除

在单链表中删除结点,需要找到要删除结点的前一个结点,然后将该结点从链表中摘除。

bool ListDelete(LinkList *L, int i, int *e) {
    LNode *p = *L;
    while (--i) {
        p = p->next;
    }
    LNode *q = p->next;
    *e = q->data;
    p->next = q->next;
    free(q);
    return true;
}

查找

在单链表中查找元素,需要遍历整个链表,逐个与待查找元素进行比较。

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

int LocateElem(LinkList L, int e) {
    LNode *p = L->next;
    int i = 1;
    while (p) {
        if (p->data == e) {
            return i;
        }
        p = p->next;
        i++;
    }
    return 0;
}

遍历

遍历单链表,需要逐个输出链表中的结点数据。

void PrintList(LinkList L) {
    L = L->next;
    while (L) {
        printf("%d ", L->data);
        L = L->next;
    }
    printf("\n");
}

2.3 示例说明

下面是一条示例说明:如何用单链表实现两个有序链表的合并。

假设有两个有序链表A和B,将它们合并成一个有序链表C。

#include <stdio.h>
#include <stdlib.h>

typedef struct LNode {
    int data;
    struct LNode *next;
} LNode, *LinkList;

LinkList CreateList(int a[], int n) {
    LinkList L = (LNode *)malloc(sizeof(LNode));
    LNode *p = L;
    for (int i = 0; i < n; i++) {
        LNode *q = (LNode *)malloc(sizeof(LNode));
        q->data = a[i];
        q->next = NULL;
        p->next = q;
        p = p->next;
    }
    return L;
}

void Merge(LinkList A, LinkList B, LinkList *C) {
    LNode *p = A->next;
    LNode *q = B->next;
    LNode *r = *C;
    while (p && q) {
        if (p->data < q->data) {
            r->next = p;
            p = p->next;
        } else {
            r->next = q;
            q = q->next;
        }
        r = r->next;
    }
    if (p) {
        r->next = p;
    }
    if (q) {
        r->next = q;
    }
}

int main() {
    int a[] = {1, 3, 5, 7};
    int b[] = {2, 4, 6, 8};
    LinkList A = CreateList(a, 4);
    LinkList B = CreateList(b, 4);
    LinkList C = (LNode *)malloc(sizeof(LNode));
    C->next = NULL;
    Merge(A, B, &C);
    PrintList(C);
    return 0;
}

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言数据结构之顺序表和单链表 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • 小米10开发者选项在哪?小米10开启开发者选项的方法

    我来为您详细讲解一下“小米10开发者选项在哪?小米10开启开发者选项的方法”。 1. 小米10开发者选项在哪? 在小米10上,开发者选项默认是隐藏的,需要您手动将其打开。操作步骤如下: 1.打开小米10设置应用。 2.向下滚动并找到“关于手机”选项并点击进入。 3.找到“MIUI版本”并点击7次。 4.出现“您现在是开发者”的提示,这时候,您就可以前往设置菜…

    other 2023年6月26日
    00
  • 深入浅出Shell编程 Shell变量介绍

    首先,Shell是Unix/Linux系统提供的一种命令行接口,它可以通过编写Shell脚本来实现自动化操作和管理,而Shell变量则是在Shell脚本中用来存储数据和传递参数的一种机制。 Shell变量类型 在Shell中,变量有以下几种类型: 环境变量:用来设置全局的操作环境,比如PATH、HOME、TERM等。 本地变量:只在当前Shell进程中有效,…

    other 2023年6月27日
    00
  • powerbi基础操作-summarizecolumns()函数

    Power BI基础操作 – summarizecolumns()函数 summarizecolumns()是Power BI中的一个DAX函数,用于对数据表中的列进行汇总计算。本攻略将介绍summarize()函数的用法,并提供两个示例。 语法 summarizecolumns()函数的语法如下: SUMMARIZEC ( <column1>,…

    other 2023年5月9日
    00
  • C++直接初始化与复制初始化的区别深入解析

    C++中,初始化对象的方式可以分为直接初始化和复制初始化。它们的区别在于,直接初始化是在变量名后面跟一对括号来完成的,而复制初始化是通过赋值号完成的。 下面我们详细讲解一下这两种初始化方式的区别: 直接初始化 直接初始化是在变量名后面跟一对括号来完成的。例如: int x(5); 在这个例子中,我们使用了直接初始化方式来创建一个整型变量x,并将其赋值为5。这…

    other 2023年6月20日
    00
  • python程序中用类变量代替global 定义全局变量

    下面是“Python程序中用类变量代替global定义全局变量”的完整攻略,包括基本原理、实现方法和两个示例说明。 基本原理 在 Python 中,可以使用 global 关键字定义全局变量,但是这种方式容易导致变量污染和命名冲突。为了避免这种情况,可以使用类变量代替 global 定义全局变量。类变量是指在类中定义的变量,可以被类的所有实例共享。 实现方法…

    other 2023年5月5日
    00
  • Android彻底清除APP数据的两种方案总结

    Android彻底清除APP数据的两种方案总结 在Android开发中,有时我们需要彻底清除应用的数据,包括缓存、数据库、SharedPreferences等。下面是两种常见的方案来实现这个目标: 方案一:使用应用管理器清除数据 Android提供了应用管理器来管理应用的信息和数据。我们可以通过应用管理器来清除应用的数据。具体步骤如下: String pac…

    other 2023年10月13日
    00
  • SQL Server误区30日谈 第3天 即时文件初始化特性可以在SQL Server中开启和关闭

    关于“SQL Server误区30日谈 第3天 即时文件初始化特性可以在SQL Server中开启和关闭”的攻略,我给出以下详细的讲解。 什么是即时文件初始化特性? 即时文件初始化特性指的是在SQL Server中创建数据库文件时,是否需要立即分配物理空间。如果开启即时文件初始化特性,那么创建数据库文件时只会为文件分配头部空间,在执行任何事务之前,并没有预先…

    other 2023年6月20日
    00
  • 晋江小说阅读中怎么修改昵称? 晋江小说修改用户名的技巧

    下面是“晋江小说阅读中怎么修改昵称? 晋江小说修改用户名的技巧”的完整攻略。 一、前置条件 在修改昵称之前,需要先登录晋江文学城账号。 二、修改昵称 在晋江文学城网站首页上方,点击“我的空间”按钮进入个人空间页面。 在个人空间页面中,找到“个性设置”栏目,点击对应的“编辑”按钮进入编辑页面。 在编辑页面中,找到“用户信息”模块下的“昵称”一项,将原昵称更改为…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部