一、数据结构是指数据元素的集合及元素间的相互关系和构造方法, 结构是指元素之间的关系. 在数据结构中,元素之间的相互关系称为数据的逻辑结构. 按照逻辑关系的不同将数据结构分为 线性结构和非线性结构, 线性结构包括线性表、栈、队列、串, 非线性结构包括 树、图. 数据元素及元素之间关系的存储形式称为存储结构, 可分为顺序存储和链式存储两种方式.
1. 线性结构的特点是数据元素之间一种线性关系, 即数据元素"一个接一个的排列", 这种结构主要用于描述具有单一 前驱和后继 的数据关系.
线性表的存储方式成为顺序存储和链式存储两种基本方式. 线性表的顺序存储称为 顺序表, 线性表的链式存储称为 链表.
顺序表:
相关操作:
//-------------------线性表的顺序存储-----------------------
#define MAXSIZE 20
typedef int ElemType;
typedef int Status;
typedef struct
{
ElemType data[MAXSIZE];
int length; // 当前线性表的长度
} SqList; // 线性表的类型
// ----------获取线性表中的元素----------
// 返回值为 int型. L为结构体变量(线性表), i为要获得的元素索引, e为int型的指针变量
Status GetElem(SqList L, int i, ElemType *e)
{
// 线性表是从 1开始的, 数组是从 0开始的
if (L.length == 0 || i < 1 || i > L.length) {
return 0;
}
*e = L.data[i-1]; // *e是指针e指向存储空间的值
return 1;
}
// ----------在线性表中插入元素----------
// arg1: 结构体指针变量(线性表指针), arg2: 要插入的位置, arg3: 要插入的元素
Status ListInsert(SqList *L, int i, ElemType e)
{
int k;
if (L->length == MAXSIZE) { //线性表满了
return 0;
}
if (i < 1 || i > L->length + 1) { // i不再范围内.(线性表从1开始)
return 0;
}
if (i <= L->length) { // 若插入的数据位置不再表尾
// 将要插入位置后的数据元素向后移动一位
for (k = L->length-1; k >= i-1; k--) {
L->data[k+1] = L->data[k];
}
}
// 将新元素插入
L->data[i-1] = e;
L->length++; // 线性表长度+1
return 1;
}
// ----------线性表中删除元素----------
Status ListDelete(SqList *L, int i, ElemType *e)
{
int k;
if (L->length == 0) { //如果是空表
return 0;
}
if (i < 1 || i > L->length) {
return 0;
}
// 返回删除的元素.(因为数组元素是从0开始的,因此要-1)
*e = L->data[i-1];
if (i < L->length) {
for (k = i; k < L->length; k++) {
L->data[k-1] = L->data[k];
}
}
// 线性表长度-1
L->length--;
return 1;
}
链表
//-------------------线性表的链式存储-----------------------
typedef struct Node
{
ElemType data; // 数据域
struct Node* next; // 指针域
} Node;
typedef struct Node *LinkList;
// ----------单链表的读取----------
// 初始条件: 顺序线性表L已存在. 用e返回L中第i个数据元素的值
// arg1: L是头指针 arg2: 获取第i个元素 arg3: e是int类型的指针变量
Status GetElem1(LinkList L, int i, ElemType *e)
{
int j;
LinkList p; // 定义指针变量p
// 令p指向第一个结点
p = L->next; //头结点->next 为链表的第一个结点
j = 1;
while (p && j < i) { // 如果结点存在 && j在i之前
p = p->next;
++j;
}
if (!p || j > i) { // 如果结点不存在 || j在i的后面
return 0;
}
// *e为int类型存储空间的值
*e = p->data; // 将获取的结点保存到*e中返回.
return 1;
}
// ----------单链表的插入----------
#include <mm_malloc.h>
/*
LinkList L: L为结构体指针,(*L)为结构体变量
LinkList *L: L为指向结构体指针的指针. 因此(*L)就是结构体指针,(**L)就是结构体变量了
*/
// arg1: 为指向结构体指针的指针 arg2:要插入元素的位置 arg3: int型 变量e
Status ListInsert1(LinkList *L, int i, ElemType e)
{
LinkList p, s;
int j = 1;
p = *L; // p指向链表的头结点
// 用于寻找第i个结点.
while (p && j < i) { // 如果p存在 && j < i(链表的插入,需要从头开始遍历,j必须要小于i)
p = p->next;
++j;
}
if (!p || j > i) {
return 0;
}
s = (LinkList)malloc(sizeof(Node)); // 查找成功, 生成新结点s
s->data = e; //给结点数据域赋值
// 插入操作
s->next = p->next; // p的后继结点 赋值给 s的后继结点(之前的p的后继结点放在s结点之后)
p->next = s; // 将s结点 赋值给 p的后继结点.
return 1;
}
// ----------单链表的删除----------
Status ListDelete1(LinkList *L, int i, ElemType *e)
{
LinkList p, q;
int j = 1;
p = *L; // P指向链表的头结点
while (p && j < i) {
p = p->next;
++j;
}
if (!p || j > i) {
return 0;
}
// 查找成功, 将删除的结点p->next赋值给q
q = p->next;
// 删除操作
p->next = q->next;
// 将q结点中的数据赋值给e并返回
*e = q->data; // 被删除结点的数据
free(q); // 释放该结点的内存
return 1;
}