基于《大话数据结构》的学习笔记
线性表(List):零个或多个数据元素的有限序列
1.顺序储存结构
线性表的数据顺序储存结构,指的是用一段地址连续的储存单元依次储存线性表的数据元素。
实现
定义顺序表
#define MAXSIZE 20 //取定顺序表最大长度
#define OK 1
#define ERROR 0
typedef int Status;
typedef struct
{
int data[MAXSIZE];
int lenth;
}SqList;
读取其中元素
Status GetElem (SqList L, int i, int *e)
{
if (L.lenth==0 || i <1 || i>L.lenth)
return ERROR; // 索引超出范围 报错
*e = L.data[i-1]; // 返回对应值
return OK;
}
插入新元素
Status ListInsert (SqList *L, int i, int e)
{
int k;
if (L->lenth == MAXSIZE) // 顺序表满 报错
return ERROR;
if (i < 1 || i > L->lenth+1) // 索引超出范围 报错
return ERROR;
if (i <= L->lenth ) {
for (k = L->lenth; k>=i-1; k--)
L->data[k+1] = L->data[k];
} // 第i个元素以后的元素都向后移一位
L->data[i-1] = e; // 第i-1个位置插入
L->lenth ++;
return OK;
}
删除旧元素
int ListDelete (SqList *L, int i, int *e)
{
int k;
if (L->lenth == 0) // 顺便表空 报错
return ERROR;
if (i < 1 || i > L->lenth) // 索引超出范围 报错
return ERROR;
*e = L->data[i-1]; // 记录删除元素
if (i < L->lenth) {
for (k = i; k < L->lenth; k ++)
L->data[k-1] = L->data[k];
} // 第i个元素以后的元素都向前移一位
L->lenth --;
return OK;
}
2.链式储存结构
线性表的链式储存结构的特点是用一组任意的储存单元储存线性表的数据元素。
单链表
链表的每个元素不仅仅存储有自身数据(数据域),还存储有其后继元素的储存地址(指针域)。即与顺序表使用天然的储存顺序不同,链表的排序基于每个元素的指针域。
这样,我们就可以通过上一个元素找到下一个元素,实现元素的“链接”。
实现
定义链表元素(结点)
#define OK 1
#define ERROR 0
typedef int Status;
typedef struct Node {
int data;
struct Node *next; // 储存下一个元素的地址
} Node;
typedef struct Node *LinkList;
读取链表中元素
Status GetElem (LinkList L, int i, int *e)
{
int j = 1;
LinkList p;
p = L->next;
while (p && j < i) {
p = p->next; // 一个个结点向前推进
++j;
}
if (!p || j>i )
return ERROR;
*e = p->data;
return OK;
}
插入新结点与删除旧结点
Status ListInsert(LinkList *L, int i, int e)
{
int j = 1;
LinkList p, q;
p = *L;
while (p && j<i ) {
p = p->next;
++j;
}
if(!p || j>i )
return ERROR;
q = (LinkList) malloc (sizeof (Node));
q->data = e;
q->next = p->next; // q 指向 r
p->next = q; // p 指向 q
return OK;
}
Status ListDelete(LinkList *L, int i, int *e)
{
int j = 1;
LinkList p, q;
p = *L;
while (p && j<i ) {
p = p->next;
++j;
}
if (!p || j<i )
return ERROR;
q = p->next;
p->next = q->next; // p 指向 r
*e = q->data;
free (q); // 释放 q
return OK;
}
两种创建方法
/*从头创建*/
void CreateListHead (LinkList *L, int n)
{
LinkList p;
int i;
srand(time(0)); // include<time.h>生成随机数
*L = (LinkList) malloc (sizeof (Node));
(*L) ->next = NULL; // 生成头结点(不储存数据 指向第一个结点)
for (i=0; i<n; i++) { // 相当于从头插入
p = (LinkList) malloc (sizeof (Node));
p->data = rand() % 100 + 1; // 初始化数据(随机)
p->next = (*L) ->next; // 此处即插入结点
(*L) ->next = p;
}
}
/*从尾创建*/
void CreateListTail (LinkList *L, int n)
{
LinkList p, q;
int i;
srand(time(0));
*L = (LinkList) malloc (sizeof (Node));
q = *L; // q 是一个指向 L 尾部的指针
for (i=0; i<n; i++){
p = (LinkList) malloc (sizeof (Node));
p->data = rand() % 100 + 1;
q->next = p; // q 指向 p
q = p; // 使得 p 再次指向 L 尾部
}
q->next = NULL;
}
清空链表
Status ClearList(LinkList *L)
{
LinkList p, q;
p = (*L) ->next;
while (p) {
q = p->next; 借助 q 往后递进 逐个删除
free(p);
p = q;
}
(*L) ->next = NULL;
return OK;
}
总结