线性表
1.线性表:具有相同数据类型的n个数据元素的有限序列,n可以为0,此时是一个空表
根据存储结构的不同,线性表可以分为:
顺序表(数组)
链表
2.顺序表:逻辑上相邻的两个元素在物理位置上也相邻的线性表
顺序表的实现及其操作:
静态实现方式:
/**@数据结构:线性表->顺序表 **@作者:9761滴 **@实现方式:静态分配(即分配固定大小的数组,数组长度不可变) **/ //一种数据结构的操作无非 创建删除,增删改查 //本文件中实现了顺序表的 /*1.创建(即初始化操作) **2.求表长 **3.查找元素(分按位查找和按值查找) **4.插入操作(在指定位序插入数据元素) *****位序指的是从1开始的整数 **5.删除操作(删除指定位序的数据元素) **6.输出整个顺序表 */ //等操作 #include<cstdio> #define MaxSize 10 #define ERR -99 typedef int ElementType; //顺序表结构体 struct SqList{ ElementType data[MaxSize]; int length; }; //初始化顺序表 void InitList(SqList *L){ L->length=0; } //求表长 int Length(SqList L){ return L.length; } //按值查找 int LocateElem(SqList L,ElementType e){ for(int i=0;i<L.length;i++){ if(L.data[i]==e){ return i+1; } } return -1; } //按位查找 ElementType GetElem(SqList L,int i){ if(i<1||i>L.length) return ERR; else return L.data[i-1]; } //插入指定位置 bool Insert(SqList *L,int i,ElementType e){ if(i<1||i>L->length+1){ printf("index error"); return false; } if(L->length>=MaxSize){ printf("SqList is full"); return false; } for(int j=L->length;j>=i;j--) L->data[j]=L->data[j-1]; L->data[--i]=e; L->length++; return true; } //删除指定位置 ElementType Delete(SqList *L,int i){ if(L->length==0){ printf("SqList is already empty"); return ERR; } if(i>L->length||<1){ printf("index error"); return ERR; } ElementType e; e=L->data[i-1]; for(int j=i-1;j<L->length-1;j++){ L->data[j]=L->data[j+1]; } L->length--; return e; } //打印刷出整个表 void PrintList(SqList L){ for(int i=0;i<L.length;i++){ printf("%d ",L.data[i]); } printf("\n"); }
动态实现方式:
/**@数据结构:线性表->顺序表 **@作者:9761滴 **@实现方式:动态分配(即分使用函数malloc (需要include stdlib.h) ,数组长度可变) **/ //一种数据结构的操作无非 创建删除,增删改查 //本文件中实现了顺序表的 /*1.创建(即初始化操作) **2.销毁表 **3.求表长 **4.查找元素(分按位查找和按值查找) **5.插入操作(在指定位序插入数据元素) *****位序指的是从1开始的整数 **6.删除操作(删除指定位序的数据元素) **7.输出整个顺序表 */ //等操作 #include<cstdio> #include<stdlib.h> #define ERR -99 typedef int ElementType; //顺序表结构体 struct SqList{ ElementType *data; int length; int MaxSize; }; //初始化表 void InitList(SqList *L){ L->length=0; L->MaxSize=10; L->data=(int*)malloc(sizeof(ElementType)*L->MaxSize); } //销毁表 void destroy(SqList *L){ free(L->data); } //求表长 int Length(SqList L){ return L.length; } //按值查找 int LocateElem(SqList L,ElementType e){ for(int i=0;i<L.length;i++){ if(L.data[i]==e){ return i+1; } } } //按位查找 ElementType GetElem(SqList L,int i){ if(i<1||i>L.length) return ERR; else return L.data[i-1]; } //指定位置插入 bool Insert(SqList &L,int i,ElementType e){ if(i<1||i>L.length+1){ printf("index error"); return false; } if(L.length>=L.MaxSize){ printf("SqList is full"); return false; } for(int j=L.length;j>=i;j--) L.data[j]=L.data[j-1]; L.data[--i]=e; L.length++; return true; } //删除指定位置元素 ElementType Delete(SqList *L,int i){ if(L->length==0){ printf("SqList is already empty"); return ERR; } if(i>L->length||i==0){ printf("index error"); return ERR; } ElementType e; e=L->data[i-1]; for(int j=i-1;j<L->length-1;j++){ L->data[j]=L->data[j+1]; } L->length--; return e; } //打印输出整个线性表 void PrintList(SqList L){ for(int i=0;i<L.length;i++){ printf("%d ",L.data[i]); } printf("\n"); }
*顺序存储、随机存储、顺序存取、随机存取的区别请参考这篇文章
3.链表
链表定义:逻辑上相邻的两个元素在物理位置上不相邻,但通过指针链接起来的线性表
单链表:每个结点除了数据域外,只有一个指针用来存放后继结点的位置信息
双链表:每个结点除了数据与外,有一个前驱结点指针和一个后继结点指针用来存放相邻的前后两个结点的位置信息
循环链表:(默认循环单链表),最后一个结点的指针指向首结点,将整个链表链接成一个环
循环双链表:自己体会吧
静态链表:静态链表预先分配一块连续的存储区域,在这个区域中使用链式存储。
静态链表的好处:随机存取和链式存取相结合
单链表的定义级操作的实现:
带头节点版本:
/**@数据结构:线性表->单链表 **@作者:9761滴 **@是否带头结点:是 **/ //一种数据结构的操作无非 创建删除,增删改查 //本文件中实现了单链表的 /*1.初始化操作 **2.单链表的建立 @尾插法 @头插法 **3.查找元素(分按位查找和按值查找) **4.插入操作 *****位序指的是从1开始的整数 单链表的插入操作相对复杂一些,包括: @ 按位序插入 @ 指定结点的后插操作 @ 指定结点的前插操作 **5.删除操作 @ 按位序删除 @ 指定结点删除 **6.输出整个顺序表 */ //等操作 #include<cstdio> #include<stdlib.h> typedef int ElementType; /** 结点结构体 **Linklist 是为了有时候强调参数是一个链表,而LNode*强调一个结点 */ typedef struct LNode{ ElementType data; struct LNode* next; }LNode,*LinkList; bool InsertAfter(LNode *p,ElementType e); //初始化链表 bool InitList(LinkList &L){ L=(LNode*)malloc(sizeof(LNode)); if(L==NULL)//内存未成功分配 ,可能原因,内存耗尽 return false; L->next=NULL; return true; } //单链表的建立 @ 尾插法 bool CreateList_Tail(LinkList &L){ L=(LinkList)malloc(sizeof(LNode)); if(L==NULL) return false; LNode *s; LNode *r; r=L->next; ElementType e; scanf("%d",&e); //此处elementType 为 int while(e!=-9999){ //-9999表示输入结束 s=(LNode*)malloc(sizeof(LNode)); s->data=e; s->next=NULL; r->next=s; r=s; scanf("%d",&e); } return true; } //单链表的建立 @ 头插法 bool CreateList_Head(LinkList &L){ L=(LinkList)malloc(sizeof(LNode)); if(L==NULL) return false; L->next=NULL; LNode *s; ElementType e; scanf("%d",&e); while(e!=-9999){ s=(LNode*)malloc(sizeof(LNode)); s->data=e; s->next=L->next; L->next=s; scanf("%d",&e); } return true; } //单链表的查找 @ 按位序查找 //&此方法规定可以查找头结点,即位序从0开始 LNode* GetElem(LinkList L,int i){ if(i<0) return NULL; LNode *pre=L; int pos=0; while(pre!=NULL&&pos<i){ pre=pre->next; pos++; } return pre; } //单链表的查找 @ 按值查找 LNode* LocateElem(LinkList L,ElementType e){ LNode *p=L->next; while(p!=NULL&&p->data!=e){ p=p->next; } return p; } //插入操作 @ 按位序插入 bool Insert(LinkList &L,int i,ElementType e){ if(i<1) return false; /**找指定位序的前一个位置 LNode* pre=L; int pos=0; while(pre!=NULL&&pos<i-1){ pre=pre->next; pos++; } if(pre==NULL) return false; **/ LNode* pre=GetElem(L,i-1); /** 修改结点之间链接关系,实现插入 LNode* s=(LNode*)malloc(sizeof(LNode)); if(s==NULL) return false;//内存分配失败 s->data=e; s->next=pre->next; pre->next=s; return true; **/ return InsertAfter(pre,e); } //插入操作 @ 指定结点后插 bool InsertAfter(LNode *p,ElementType e){ if(p==NULL) return false; LNode *q=(LNode*)malloc(sizeof(LNode)); if(q==NULL) return false;//内存分配失败 q->data=e; q->next=p->next; p->next=q; return true; } //插入操作 @ 指定结点前插 bool InsertBefore(LNode *p,ElementType e){ if(p==NULL) return false; LNode *q=(LNode*)malloc(sizeof(LNode)); if(q==NULL) return false;//内存分配失败 q->next=p->next; p->next=q; q->data=p->data; p->data=e; return true; } //删除操作 @ 按位序删除 bool Delete(LinkList &L,int i,ElementType &e){ if(i<1) return false; /**找指定位序的前一个位置 LNode* pre=L; int pos=0; while(pre!=NULL&&pos<i-1){ pre=pre->next; pos++; } **/ LNode *pre=GetElem(L,i-1); //删除结点 if(pre==NULL) //要删除的结点不存在 return false; if(pre->next==NULL) //要删除的结点不存在 return false; LNode* q=pre->next; e=q->data; pre->next=q->next; free(q); return true; } //删除操作 @删除指定结点 //&此方法有局限性,如果p是最后一个结点,则无法成功删除, 但此方法的时间复杂度为o(1) bool DeleteNode(LNode *p){ if(p==NULL) return false; LNode *q=p->next; p->data=q->data; p->next=q->next; free(q); return true; }
不带头节点版本
/**@数据结构:线性表->单链表 **@作者:9761滴 **@是否带头结点:否 **/ //一种数据结构的操作无非 创建删除,增删改查 //本文件中实现了单链表的 /*1.初始化 **2.单链表的建立 @尾插法 @头插法 **3.查找元素(分按位查找和按值查找) **4.插入 *****位序指的是从1开始的整数 单链表的插入操作相对复杂一些,包括: @ 按位序插入 @ 指定结点的后插操作 @ 指定结点的前插操作 **5.删除 @ 按位序删除 @ 指定结点删除 **6.输出整个顺序表 */ //等操作 #include<cstdio> #include<stdlib.h> typedef int ElementType; /** 结点结构体 **Linklist 是为了有时候强调参数是一个链表,而LNode*强调一个结点 */ typedef struct LNode{ ElementType data; struct LNode* next; }LNode,*LinkList; bool InsertAfter(LNode *p,ElementType e); //初始化链表 bool InitList(LinkList &L){ L=NULL; //空表,暂时没有任何结点 return true; } //单链表的建立 @ 尾插法 bool CreateList_Tail(LinkList &L){ L=(LNode*)malloc(sizeof(LNode)); if(L==NULL) return false; LNode *s; LNode *r; r=L; ElementType e; scanf("%d",&e); //此处elementType 为 int r->data=e; scanf("%d",&e); while(e!=-9999){ //-9999表示输入结束 s=(LNode*)malloc(sizeof(LNode)); s->data=e; s->next=NULL; r->next=s; r=s; scanf("%d",&e); } return true; } //单链表的建立 @ 头插法 bool CreateList_Head(LinkList &L){ L=(LNode*)malloc(sizeof(LNode)); if(L==NULL) return false; LNode *s; ElementType e; L->data=e; L->next=NULL; scanf("%d",&e); while(e!=-9999){ s=(LNode*)malloc(sizeof(LNode)); s->data=e; s->next=L->next; L->next=s; scanf("%d",&e); } return true; } //单链表的查找 @ 按位序查找 LNode* GetElem(LinkList L,int i){ if(i<1) return NULL; LNode *pre=L; int pos=1; while(pre!=NULL&&pos<i){ pre=pre->next; pos++; } return pre; } //单链表的查找 @ 按值查找 LNode* LocateElem(LinkList L,ElementType e){ LNode *p=L->next; while(p!=NULL&&p->data!=e){ p=p->next; } return p; } //插入操作 @ 按位序插入 bool Insert(LinkList &L,int i,ElementType e){ if(i<1) return false; if(i==1){ LNode *s=(LNode*)malloc(sizeof(LNode)); if(s==NULL) return false; s->data=e; s->next=L; L=s; return true; } /**找指定位序的前一个位置 LNode* pre=L; int pos=0; while(pre!=NULL&&pos<i-1){ pre=pre->next; pos++; } if(pre==NULL) return false; **/ LNode* pre=GetElem(L,i-1); /** 修改结点之间链接关系,实现插入 LNode* s=(LNode*)malloc(sizeof(LNode)); if(s==NULL) return false;//内存分配失败 s->data=e; s->next=pre->next; pre->next=s; return true; **/ return InsertAfter(pre,e); } //插入操作 @ 指定结点后插 bool InsertAfter(LNode *p,ElementType e){ if(p==NULL) return false; LNode *q=(LNode*)malloc(sizeof(LNode)); if(q==NULL) return false;//内存分配失败 q->data=e; q->next=p->next; p->next=q; return true; } //插入操作 @ 指定结点前插 bool InsertBefore(LNode *p,ElementType e){ if(p==NULL) return false; LNode *q=(LNode*)malloc(sizeof(LNode)); if(q==NULL) return false;//内存分配失败 q->next=p->next; p->next=q; q->data=p->data; p->data=e; return true; } //删除操作 @ 按位序删除 bool Delete(LinkList &L,int i,ElementType &e){ if(i<1) return false; if(i==1){ LNode *pre=L; L=L->next; if(pre==NULL) return false; free(pre); return true; } /**找指定位序的前一个位置 LNode* pre=L; int pos=0; while(pre!=NULL&&pos<i-1){ pre=pre->next; pos++; } **/ LNode *pre=GetElem(L,i-1); //删除结点 if(pre==NULL) //要删除的结点不存在 return false; if(pre->next==NULL) //要删除的结点不存在 return false; LNode* q=pre->next; e=q->data; pre->next=q->next; free(q); return true; } //删除操作 @删除指定结点 //&此方法有局限性,如果p是最后一个结点,则无法成功删除, 但此方法的时间复杂度为O(1) bool DeleteNode(LNode *p){ if(p==NULL) return false; LNode *q=p->next; p->data=q->data; p->next=q->next; free(q); return true; }
双链表的实现
/**@数据结构:线性表->双链表 **@作者:9761滴 **@是否带头结点:是 **/ //一种数据结构的操作无非 创建删除,增删改查 //本文件中实现了双链表的 /*1.初始化 **2.插入(后插) **3.删除(后删) **4.销毁 */ //等操作 #include<cstdio> #include<stdlib.h> typedef int ElementType; /** 双链表的结点的结构体 **DLinklist 是为了有时候强调参数是一个双链表,而DNode*强调一个结点 */ typedef struct DNode{ ElementType data; DNode *prior; DNode *next; }DNode,*DLinkList; //初始化链表 bool InitList(DLinkList &L){ L=(DNode*)malloc(sizeof(DNode)); if(L==NULL)//内存未成功分配 ,可能原因,内存耗尽 return false; L->prior=NULL; L->next=NULL; return true; } //插入操作 @ 指定结点后插 bool InsertAfter(DNode *p,ElementType e){ if(p==NULL) return false; DNode *q=(DNode*)malloc(sizeof(DNode)); if(q==NULL) return false; q->data=e; q->next=p->next; if(q->next!=NULL) q->next->prior=q; q->prior=p; p->next=q; return true; } //删除操作 @ 指定结点后删 bool DeleteAfter(DNode *p){ if(p==NULL||p->next==NULL) return false; DNode *q=p->next; p->next=p->next->next; if(p->next->next!=NULL) p->next->next->prior=p; free(q); return true; } //销毁表 void Destory(DLinkList &L){ while(L->next!=NULL){ DeleteAfter(L); } free(L); L=NULL; }
静态链表的实现
/**@数据结构:线性表->静态链表 **@作者:9761滴 **@是否带头结点:是 **/ #include<cstdio> #include<stdlib.h> #define MAXSIZE 10 typedef int ElementType; //静态链表结点的结构,SLinkList[MAXSIZE]表示声明了一个maxsize大小的数组 typedef struct SNode{ ElementType data; int next; }SNode,SLinkList[MAXSIZE]; //静态链表的初始化 bool InitList(SLinkList &L){ L[0].next=-1; //-1表示该结点后续无结点 for(int i=1;i<MAXSIZE;i++){ L[i].next=-2; //-2表示该结点未使用,方便后续插入操作 } return true; } int main(){ return 0; }