文章目录
前言
提示:本篇记录自学《大话数据结构》的链表章节
主要是代码的理解,不会出现很多的概念定义
学习数据结构最好的办法就是画图相当于是一步步调试
一、顺序存储之顺序表
定义
顺序表也叫(顺序存储结构) ,是一种用一段地址连续的存储单元依次存储线性表的数据元素。
顺序表的示意图
二、线性表的顺序存储结构
#define Max_sz 20 /代表数组最大容量
typedef int ElemType; /代表元素类型
typedef sturct
{
ElemType data[Max_sz];
int length: /记录数组中元素的有效个数
}SqList; /重定义这个结构体的名字叫SqList也就是顺序表的意思
SqList 的数组存放元素 length记录有效元素个数
三.顺序表的增删查改
通过下标 查询函数
前提:顺序表以创立
代码如下:
#typedef int Status; /Status 是返回值的类型的意思
#define OK 1 /代表成功查找
#define ERROR 0 /代表查找失败
Status GetElem(SqList L, int i, ElemType* e)
{
if(L.length ==0 || i<1 || i>L.length) //报错的条件
return ERROR;
*e=L.data[i-1]; //返回目标元素给e
return OK;
}
详解
if(L.length ==0 || i<1 || i>L.length)
三个条件:length不能为0为0就代表是空表 || 查找的下标不能小于1 || 查找下标不能大于有效长度
因为数组下标是从0开始,而位置理所当然是1开始 所以*e =data[i-1]
通过下标 插入函数
前提:顺序表以创立
代码如下:
// Status 是返回值的类型的意思 #typedef int Status;
Status Eleminsert(SqList* L, int i, ElemType e)
{
int k;
if( L->length == Max_sz || i<1 || i > L->length+1)
return ERROR;
if(i<=L->length) //元素遍历后移
{
for(k=L->length-1;k>=i;k++)
L->data[k+1]=L->data[k];
}
L->data[i-1]=e;
L->length++; //插入完长度要加1
return OK;
}
详解
if( L->length == Max_sz || i<1 || i > L->length+1)
三个条件:当length ==max_sz 说明列表满了 || 不解释 || 这里length+1 是因为可以插在最后
if(i<=L->length)
当你插入的位置不是在表尾 就需要进行数组的后移
for(k=L->length-1;k>=i;k--)
后移我们肯定是要从最后一个开始移动 要不然会把前面的数据覆盖
k=L->length-1
下标的最后一个元素(因为数组是从0下标开始)
k>=i
因为原i下标的元素也许后移
通过下标 删除函数
前提:顺序表以创立
代码如下:
Status Elemdel(SqList* L,int i, ElemType* e)
{
int k;
if (L->length == 0 || i < 1 || i > L->length )
return ERROR;
*e = L->data[i - 1];
if (i < L->length) //当删除元素不在表尾 数组往前移
{
for (k = i; k < L->length ; k++)
{
L->data[k-1] = L->data[k];
}
}
L->length--;
return OK;
}
详解
for (k = i; k < L->length ; k++)
这里让 k=i 是因为要把i下标也覆盖。
通过下标 修改函数
前提:顺序表以创立
代码如下:
Status GetElem(SqList * L, int i, ElemType e)
{
if(L->length == 0 || i<1 || i> L->length)
return ERROR;
L->data[i-1]=e;
return OK;
}
四、链式存储之单链表
定义
链表中两个逻辑位置在一起的元素,物理地址并不连续,因为链表的每个会有一个指向下一项的指针,指针所指地址对应的值才是与该元素逻辑上相邻的值。本文我们会从单链表出发,循序渐进带大家了解双链表和循环链表。
单链表的示意图
五、单链表的链式存储结构
代码如下(示例):
注意:本篇博客都为有头结点的单链表;
typedef struct Node
{
ElemType data; //数据域
struct Node*next; //指针域
}Node;
typedef Node* Linklist;
六、顺序表的增删查创
通过下标 查找元素
前提:顺序表以创立
代码如下:
#define OK 1
#define ERROR -1
typedef int Status;
Status GetElem(Linklist L,int i ,ElemType e)
{
int j;
Linklist p; //创立指针p
p=L->next; //指针p指向头节点的下一个元素==首元素
j=1; //计数器
while(p && j<i) //当p指针不为空 并且 让j小于i
{
p=p->next; // 让p遍历指向下一个结点
++j; //这轮循环的目的是要让指针p指向要查找的下标的前一个 元素
}
if(P || j>i) //当指针为NULL 或者j大于i
return ERROR;
*e=p->data;
return Ok;
}
通过下标 插入元素
前提:顺序表以创立
代码如下:
void Insert Elem(Linklist * L,int i.ElemType e)
{
int j;
Linklist p,s; //开辟两个指针
j=1;
while(p && j<i)
{
p=p->next; //p指向下个结点
j++;
}
if(!p || j>i) //当p!=NULL时 且 j> i
return ERROR ;
s=( (Linklist)
s->data=e;
s->next=p->next;
p->next = s;
return Ok;
}
详解
通过下标 删除元素
前提:顺序表以创立
代码如下:
status Linklist (Linklist * L,int i,ElemType *e)
{
int j;
Linklist p,q;
p=*L;
j=1;
while(p- && j<i)
{
p=p->next;
}
if( ! (p->next) && (j>i))
return ERROR;
q=p->next ;
p->next=q->next;
*e=q->next;
free(q);
return OK;
}
详解图
单链表的整表创立
1.头插法 (类似于栈 先进后出)
前提:顺序表以创立
代码如下:
// 二级指针
void Createlist(Linklist *L ,int n)
{
Linklist p;
*L = (Linklist)malloc(sizeof(Node)); //动态开辟一个带头结点的单链表
(*L)->next=NULL; //让头结点的头指针指向NULL
for(int i;i<n;i++)
{
p=(Linklist)malloc(sizeof(Node)); //每次循环都动态开辟一块空间
p->data =i;
p->next=(*L)->next;
(*L)->next=p;
}
}
详解图
2.尾插法
前提:顺序表以创立
代码如下:
void Createlist(Linklist *L ,int n)
{
Linklist p,r;
*L = (Linklist)malloc(sizeof(Node)); //动态开辟一个带头结点的单链表
r=(*L); //让r指向L 即 r=L
for(int i;i<n;i++)
{
p=(Linklist)malloc(sizeof(Node)); //每次循环都动态开辟一块空间
p->data =i;
r->next=p;
r=p;
}
r->next =NULL;
}
详解
单链表的整表删除
前提:顺序表以创立
代码如下:
Status Clearlist(Linklist *L)
{
Linklist p,d;
p=(*L)->next;
while(p)
{
d=p->next;
free(p);
p=d;
}
(*L)->next=NULL;
return OK;
}
详解
总结
这是琢磨了一天想出来的因为底子不好不是科班学这个,所以画图好理解一些,如果你不理解可以画画图。