目录
一、线性表
1.1、顺序表
1.1.1、定义顺序表(静态分配)
1.1.2、初始化InitList(&L)(静态分配)
1.1.3、定义顺序表(动态分配)
1.1.4、初始化InitList(&L)(动态分配)
1.1.5、插入元素ListInsert(&L, i, e)
1.1.6、删除元素ListDelete(&L, i, &e)
1.1.7、按值查找 LocateElem(&L, i, e)
1.1.8、测试
1.2、单链表
1.2.1、定义链表
1.2.2、初始化链表
1.2.3、头插法
1.2.4、尾插法
1.2.5、按序号查找节点
1.2.6、按值查找节点
1.2.7、插入元素
1.2.8、删除元素
1.3、双链表
1.3.1、双链表的类型定义
1.3.2、双链表的插入操作
1.3.3、双链表的删除操作
线性表一般包含以下功能:
初始化线性表:将一个线性表进行初始化,得到一个全新的线性表。
获取指定位置上的元素:直接获取线性表指定位置i上的元素。
获取元素的位置:获取某个元素在线性表上的位置i。
插入元素:在指定位置i上插入一个元素。
删除元素:删除指定位置i上的一个元素。
获取长度:返回线性表的长度。
线性表的结构一般有两种,一种是顺序存储实现,还有一种是链式存储实现。
#define Maxsize 50 //定义线性表最大长度
typedef int ElemType; //定义元素类型
typedef struct { //定义结构体
ElemType data[Maxsize]; //定义顺序表的元素
int length; //定义线性表的长度
}SqList;
void InitList(SqList *L){
L -> length = 10;
}
typedef int ElemType; //定义元素类型
typedef struct { //定义结构体
ElemType *data; //定义顺序表的元素
int length; //定义线性表的长度
int Maxsize; //定义最大长度
}SqList;
_Bool InitList(SqList *L){
L->length = 10;
L->data = malloc(sizeof (ElemType) * L->length); //malloc函数手动申请一片空间
if(L->data == NULL) return false; // 如果申请的结果为NULL表示内存空间分配失败
L->Maxsize = 0; //默认长度0
return true;
}
//在位置i插入元素e
_Bool ListInsert(SqList *L, int i, ElemType e){
if(i < 1 || i > L->length + 1) return false; //判断i是否合法,小于1或者大于最大长度返回false
if(L->length > L->Maxsize) return false; //存储空间已满,不可插入
// j为顺序表的长度,将j向i靠近(j--)到达i的位置
for (int j = L->length; j >= i; j--) {
L->data[j] = L->data[j - 1]; //将j位置的元素后移一位,通过for不断循环直到到达i位置,此时候原数组中i位置空缺
}
L->data[i - 1] = e; //此时j在i的位置,由于顺序表从0开始,在i位置就是在L.data[j-1]插入
L->length++; //顺序表长度+1
return true;
}
//在第i个位置删除元素e
_Bool ListDelete(SqList *L, int i, ElemType *e){
if(i < 1 || i > L->length + 1) return false; //判断i是否合法,小于1或者大于最大长度返回false
e = L->data[i - 1]; //将第i个位置的元素赋给e,此时顺序表中第i个位置空
for (int j = i; j < L->length; j++) {
L->data[j - 1] = L->data[j]; //循环,将第j个赋给第j-1个,也就是向前放
}
L->length--; //长度减1
return true;
}
//按值查找
int LocateElem(SqList *L, ElemType e) {
int i;
for (i = 0; i < L->length; i++) { //遍历顺序表
if (L->data[i] == e) return i + 1; //当L.data[i] == e时,返回该元素的位序,i是该元素的下标
}
return 0;
}
#include
#include
#include
typedef int ElemType;
//定义一个顺序表,动态存储
typedef struct {
ElemType *data;
int length,Maxsize;
}SqList;
//初始化一个顺序表
_Bool InitList(SqList *L){
L->data = malloc(sizeof (ElemType) * L->length);
if(L->data == NULL) return false;
L->length = 0; //初始化为0
L->Maxsize = 50; // 定义最大长度
return true;
}
//插入元素
//在i位置插入元素e
_Bool ListInsert (SqList *L, int i, ElemType e){
if(i < 1 || i > L->length + 1) return false;
if(i > L->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, ElemType *e){
if(i < 1 || i > L->length + 1) return false;
if(i > L->Maxsize) 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 ListSize(SqList *L){
return L->length;
}
//按值查找
int LocateElem(SqList *L, ElemType e) {
int i;
for (i = 0; i < L->length; i++) { //遍历顺序表
if (L->data[i] == e) return i + 1; //当L.data[i] == e时,返回该元素的位序,i是该元素的下标
}
return 0;
}
void printList(SqList *L){
for (int i = 0; i < L->length; ++i) {
printf("%d", L->data[i]);
}
printf("\n");
}
int main() {
SqList L;
InitList(&L);
ListInsert(&L, 1, 6);
printList(&L);
ListInsert(&L, 2, 44);
printList(&L);
ListInsert(&L, 3, 444);
printList(&L);
}
链表不同于顺序表,顺序表采用数组作为存储容器,需要分配一块连续且完整的内存空间进行使用,而链表则不需要,它通过一个指针来连接各个分散的节点,形成一个链状的结构。它不需要申请连续的空间,只需要按照顺序连接即可,逻辑上依然相邻。
typedef int ElemType;
typedef struct LNode{
ElemType data; //数据域
struct LNode * next; //指向下一节点的指针
}LNode, *LinkList;
void InitList(LNode *L){ // 将定义的结构体命名为L
L->next = NULL; // 链表L中的next指针指向NULL
}
//头插法
LinkList List_HeadInsert(LinkList &L){
LNode *s; int x; //定义结点指针s,插入数据x
L = (LinkList)malloc(sizeof (LNode)); //创建头结点,前面表示LinkList型的
L->next = NULL; //初始化链表,指针指向NULL
scanf("%d", &x); //输入结点的值,也就是数据域
while (x!=9999) { //输入9999时表示结束链表创建
s = (LNode *) malloc(sizeof(LNode)); //创建一个新的,待插入的结点
s->data = x;
s->next = L->next;
L->next = s;
scanf("%d", &x); //继续读取数据,读一次插一次
}
return L;
}
//尾插法
LinkList List_TailInsert(LinkList L){
int x; //数据域
L = (LinkList) malloc(sizeof (LNode)); //为链表开创一段内存空间
LNode *s, *r=L; //定义两个指针,其中r是表尾指针,s是指向新结点的指针
scanf("%d", &x); //通过输入接受到数据x
while (x!=9999) {
s = (LNode *) malloc(sizeof(LNode)); //为待插入的结点赋予一段内存空间
s->data = x;
r->next = s;
r = s;
scanf("%d", &x);
}
r->next = NULL; //表尾指针置空
return L;
}
//按序号查找节点,序号为i
_Bool GetElem(LinkList L, int i) {
if (i < 1) return 0; //当序号小于1时,此时不存在,返回0
int j = 1; //计数
LNode *p = L->next; //第一个位置赋值给p
while (p != NULL && j < i) { //当jnext; //当j
LNode *LocateElem(LinkList L, ElemType e){ //待查找的链表L 数据元素为e
LNode *p = L->next; // p指向头结点
while (p!=NULL && p->data != e) // 当p为空或查找到p的数据域为e时跳出循环
p = p->next; // 没找到,向后指,p指向下一节点
return p;
}
P = GetElem(L, i-1); //调用GetElem函数找到前驱节点
s -> next = p -> next; // 结构同前面头插法
p -> next = s;
p = GetElem(L, i-1); //调用GetElem函数获取待删除元素前一个位置
q = p -> next; // q指针指向待删除结点
p -> next = q -> next; // p指向q的后一个结点
free(q); // 释放q结点
typedef int ElemType;
//定义双链表的结点类型
typedef struct DNode{
ElemType data; //数据域
struct DNode *prior, *next; // 前驱结点的指针;后继结点的指针
}DNode, *DLinklist;
一图胜千言
s -> next = p -> next;
p -> next -> prior = s;
s -> prior = p;
p -> next = s;
p->next = q->next;
q->next->prior=p;
free(q);