2021-1-23数据结构总结(1)
作者:互联网
线性表包含顺序表(顺序存储)和链表(链式存储)
1、静态分配的顺序表实现
#include<stdio.h>
#define MaxSize 10 //定义最大长度
typedef struct{
int data[MaxSize]; //静态数组存放数据元素
int length; //定义当前长度
}SqList;
//基本操作--初始化一个顺序表
void InitList(Sqlist &L){
for(int i=0; i<MaxSize; i++)
L.data[i]=0; //将所有数据元素设置为默认初始值
L.length=0; //初始长度为0
}
//基本操作--向顺序表插入新元素
bool ListInsert(SqList &L, int i; int e){
if(i<1||i>L.length+1) //判断i的范围是否有效,顺序表下标从1开始,但是数组下标从0开始
return false;
if(L.length>=MaxSize) // 当前存储空间已满,不能插入
return false;
for(int j=L.length; j>=i; j--) //将第i个及之后的元素向后移
L.data[j]=L.data[j-1];
L.data[i-1]=e; //第i个位置放入e
L.length++:
return ture;
}
//时间复杂度:最好、最坏、平均 ==== O(1)、O(n)、O(n)
//基本操作--向顺序表删除新元素
bool ListDelect(SqList &L, int i; int &e){ //删除的值e需要返回,加上取地址符&
if(i<1||i>L.length+1) //判断i的范围是否有效,顺序表下标从1开始,但是数组下标从0开始
return false;
e=L.data[i-1]; //将被删除的值赋值给e
for(int j=i; j<L.length; j++) //将第i个位置后的元素前移
L.data[j-1]=L.data[j]; //顺序表下标从1开始,但是数组下标从0开始
L.length--;
return ture;
}
//时间复杂度:最好、最坏、平均 ==== O(1)、O(n)、O(n)
int main(){
SqList L; //声明一个顺序表
InitList(L); //初始化顺序表
//.........
for(int i=0; i<L.length; i++) //访问并打印顺序表各个元素
printf("data[%d]=%d\n", i, L.data[i]);
ListInsert(L,3,3);
int e=-1;
if(ListDelect(L, 3, e))
printf("已删除第3个元素,删除元素值为=%d\n",e);
else
printf("位序i不合法,删除失败\n");
return 0;
}
2、动态分配的顺序表实现
#include<stdlib.h> //malloc、free函数的头文件
#define InitSize 10 //默认最大长度
typedef struct{
int *data; //指示动态分配数组的指针
int MaxSize; //顺序表的最大容量
int length; //定义当前长度
}SqList;
//基本操作--初始化一个动态分配的顺序表
void InitList(Seqlist &L){
//用malloc函数申请一片连续的存储空间
L.data=(int *)malloc(InitSize*sizeof(int));
L.length=0;
L.MaxSize=InitSize;
}
//基本操作--增加动态数组的长度
void IncreaseSize(SeqList &L,int len){
int *p=L.data; //重新定义一个指针,指向原数据
L.data=(int *)malloc((L.MaxSize+len)*sizeof(int)); //重新申请一片增加长度的顺序表
for(int i=0; i<L.length; i++){ //将原本的数据复制到新区域
L.data[i]=p[i];
}
L.MaxSize=L.MaxSize+len;
free(p); //释放原来的内存空间
}
//基本操作--顺序表的按位查找
ElemType GetElem(SeqList L, int i){
return L.data[i-1];
}
//基本操作--顺序表的按值查找
int LocateElem(SeqList L, ElemType e){
for(int i=0; i<L.length; i++)
if(L.data==e)
return i+1; //下标为i的元素值为e,返回其位序i+1
return 0;
}
//时间复杂度:最好、最坏、平均 ==== O(1)、O(n)、O(n)
int main(){
SqList L; //声明一个顺序表
InitList(L); //初始化顺序表
//......向顺序表中随意插入几个元素....
IncreaseSize(L, 5);
return 0;
}
3、带头结点单链表的实现
#include<stdlib.h> //malloc、free函数的头文件
typedef struct LNode{
ElemType data; //每个结点存放一个数据元素
struct LNode *next; //指针指向下一个结点
}LNode, *LinkList;
/*
表示一个单链表,只需声明一个头指针L
LNode *L; //强调这是一个结点
LinkList L; //强调这是一个单链表
以上都能声明一个头结点,两句效果相同
*/
//初始化一个单链表(带头结点)
bool InitList(LinkList &L){
L = (LNode *)malloc(sizeof(LNode));
if(L==NULL) //内存不足,分配失败
return false;
L->next=NULL; //头结点之后没有结点
return true;
}
//尾插法建立单链表
LinkList List_TailInsert(LinkList &L){
int x;
L=(LinkList)malloc(sizeof(LNode)); //创建头结点
LNode *s,*r=L;
scanf("%d",&x);
while(x!=9999){ //输入结点值为9999表示结束
s=(LNode *)malloc(sizeof(LNode));
s->data=x;
r->next=s;
r=s; //永远保持r在最后一个结点
scanf("%d",&x);
}
r->next=NULL;
return L;
}
//头插法建立单链表
LinkList List_HeadInsert(LinkList &L){
LNode *s; int x;
L=(LinkList)malloc(sizeof(LNode)); //创建头结点
L->next=NULL; //初始为空链表
scanf("%d",&x);
while(x!=9999){ //输入结点值为9999表示结束
s=(LNode *)malloc(sizeof(LNode));
s->next=x;
s->next=L->next;
L->next=s;
scanf("%d",&x);
}
return L;
}
//头插法创建的链表输入的元素与实际存储顺序相反
//指定结点的后插操作
bool InsertNextNode(LNode *P, ElemType e){
if(p==NULL)
return false;
LNode *s = (LNode *)malloc(sizeof(LNode));
if(s==NULL) //内存分配失败
return false;
s->data=e;
s->next=p->next;
p->next=s;
return true;
}
//指定结点的前插操作
bool InsertPriorNode(LNode *P, ElemType e){
if(p==NULL)
return false;
LNode *s = (LNode *)malloc(sizeof(LNode));
if(s==NULL) //内存分配失败
return false;
s->next=p->next;
p->next=s; //将结点S插入
s->data=p->data; //将p与s的数据互换
p->data=e; //将e值覆盖p中元素
return true;
}
//单链表按位查找,返回第i个元素
LNode * GetElem(LinkList L, int i){
if(i<0)
return false;
LNode *p; //指针p指向当前扫描到的结点
int j=0; //表示p指向的是第几个结点
p=L; //初始p指向头结点
while(p!=NULL&&j<i){ //循环找到第i个结点
p=p->next;
j++;
}
return p;
}
//按值查找
LNode * LocateElem(LinkList L, ElemType e){
LNode *p=L->next;
while(p!=NULL&&p->data!=e)
p=p->next;
return p;
}
//按位序插入(带头结点)
bool ListInsert(LinkList &L, int i, ElemType e){
if(i<1)
return false;
LNode *p=GetElem(L,i-1); //找到第i-1个结点
return InsertNextNode(p,e);
}
//删除指定结点P
bool DeleteNode(LNode *P){
if(p==NULL||p->netx==NULL) //P不能是最后一个结点
return false;
LNode *q=p->next; //令q指向*p的后继结点
p->data=p->next->data; //和后继结点交换数据域
p->next=q->next; //将*q结点从链中断开
free(q);
return true;
}
//按位序删除(带头结点)
bool ListDelect(LinkList &L, int i, ElemType &e){
if(i<1)
return false;
LNode *p=GetElem(L,i-1); //找到第i-1个结点
e=p->data;
return DeleteNode(P);
}
//判断单链表是否为空(带头结点)
bool Empty(LinkList L){
return(L->next==NULL);
}
//如果不带头结点,则是return(L==NULL);
void test(){
LinkList L; //声明一个指向单链表的指针
//初始化一个空单链表
InitList(L);
return 0;
}
4、双链表的实现
#include<stdlib.h>
typedef struct DNode{
ElemType data;
struct DNode *prior,*next;
}DNode, *DLinkList;
//初始化一个双链表(带头结点)
bool InitDLinkList(DLinkList &L){
L = (DNode *)malloc(sizeof(DNode));
if(L==NULL) //内存不足,分配失败
return false;
L->prior=NULL; //头结点的prior永远指向NULL
L->next=NULL; //头结点之后暂时没有结点
return true;
}
//双链表的插入--在p结点之后插入s结点
bool InsertNextDNode(DNode *p, DNode *s){
if(p==NULL||s==NUll)
return false;
s->next=p->next;
if(p->next!=NULL) //如果p没有后继结点
p->next->prior=s;
s->prior=p;
p->next=s;
}
//双链表的删除--删除p结点的后继结点
bool DeleteNextDNode(DNode *P){
if(p==NULL)
return false;
DNode *q=p->next;
if(q==NULL)
return false;
p->next=q->next;
if(q->next!=NULL)
q->next->prior=p;
free(q);
return ture;
}
void DestoryList(DLinkList &L){
while(L->next!=NULL)
DeleteNextDNode(L);
free(L);
L=NULL;
}
//判断双链表是否为空(带头结点)
bool Empty(DLinkList L){
return(L->next==NULL);
}
void testDLinkList(){
DLinkList L;
InitDLinkList(L);
......
return 0;
}
标签:结点,NULL,return,LNode,23,int,next,2021,数据结构 来源: https://blog.csdn.net/weixin_42637873/article/details/122650731