基本数据结构之线性表-顺序表
2013-08-23 20:14
190 查看
数据结构有线性结构和非线性结构之分,本数据结构系列将从线性结构讲到非线性结构,并对这些数据结构进行精简实现(C/C++)。
1、线性结构之线性表
线性表是这样一种结构,它包含n(n>=0)个数据元素,每个数据元素成为线性表的结点;其中a[0],a[1],a[2]......,a[n-1]组成的有限序列。
数据元素的个数n称为线性表的长度 = list.length(),当长度为空时,成为空表。
将非空的(n>0)线性表表示为:a[0],a[1],a[2]......,a[n-1].
其中数据元素a[i]只是一个抽象符号,具体元素是什么类型要看具体的情况。
一个数据元素并不要求是原子的,可以有若干数据项组成。每个数据元素成为记录,含有大量记录的线性表又称为文件。这种结构必须具有以下特点:存在一个唯一的没有前驱的(头)数据元素;存在一个唯一的没有后继的(尾)数据元素;此外,每一个数据元素均有一个直接前驱和一个直接后继数据元素。
下面介绍顺序表的C语言实现。
/** @function the basic operation on List* @author lz* @date 2013.8.18*/
//线性表的动态分配存储结构#define LIST_INIT_SIZE 10 /* 线性表存储空间的初始分配量 */#define LIST_INCREMENT 2 /* 线性表存储空间的分配增量 */typedef struct { ElemType *elem; /* 存储空间基址 */ int length; /* 当前长度 */ int listsize; /* 当前分配的存储容量(以sizeof(ElemType)为单位) */}SqList;
//基本操作
/* 顺序表示的线性表的基本操作(12个) */void InitList(SqList *L){ /* 操作结果: 构造一个空的顺序线性表L */ L->elem = malloc(LIST_INIT_SIZE*sizeof(ElemType)); if(!L->elem) exit(1);/* 存储分配失败 */ L->length = 0; /* 空表长度为0 */ L->listsize = LIST_INIT_SIZE; /* 初始存储容量 */}
/* 初始条件:顺序线性表L已经存在.操作结果:销毁线性表L */void DestroyList(SqList *L){ free(L->elem); L->elem = NULL; L->length = 0; L->listsize = 0;}
/* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */void ClearList(SqList *L){ L->length = 0;}
/* 初始条件:顺序线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */Status ListEmpty(SqList L){ if(L.length == 0) return TRUE; else return FALSE;}
/* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数 */int ListLength(SqList L){ return L.length;}
/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L)。操作结果:用e返回L中第i个数据元素的值 */Status GetElem(SqList L, int i, ElemType *e){ if(i < 1 || i > L.length) return ERROR; *e = (L.elem + i - 1); return OK;}
/* 初始条件:顺序线性表L已存在,compare()是数据元素判定函数(满足为1,否则为0) *//* 操作结果:返回L中第1个与e满足关系compare()的数据元素的位序。 *//* 若这样的数据元素不存在,则返回值为0。 */int LocateElem(SqList L, ElemType e, Status(*compare)(ElemType,ElemType)){ ElemType *p; int i = 1; /* i的初始值为第一个元素的位置 */ p = L.elem; /* p的初始值为第一个元素的存储位置 */ while(i <= L.length && !compare(*p++,e)) ++i; if(i <= L.length) return i; else return 0;}
/* 初始条件:顺序线性表L已存在 *//* 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱, *//* 否则操作失败,pre_e无定义 */Status PriorElem(SqList L, ElemType cur_e, ElemType *pre_e){ int i = 2; ElemType *p = L.elem + 1; while(i <= L.length && *p != cur_e) { /*?为什么前面使用函数指针,但是此却却直接使用值比较呢?*/ p++; i++; } if(i > L.length) return INFEASIBLE; /* 操作失败 */ else { *pre_e = *--p; return OK; }}
/* 初始条件:顺序线性表L已存在 *//* 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继, *//* 否则操作失败,next_e无定义 */Status NextElem(SqList L, ElemType cur_e, ElemType *next_e){ int i = 1; ElemType *p = L.elem; while(i < L.length && *p != cur_e) { i++; p++: } if(i == L.length) return INFEASIBLE; /* 操作失败 */ else { *next_e = *++p; return OK; }}
/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L)+1 *//* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */Status ListInsert(SqList *L, int i, ElemType e){ ElemType *newbase, *p, *q; if(i < 1 || i > L->length + 1) /* i值不合法 */ return ERROR; if(L->length >= L->listsize) /* 当前存储空间已满,增加存储分配 */ { newbase = realloc(L->elem, (L->listsize + LIST_INCREMENT)*sizeof(ElemType)); if(!newbase) exit(1); /* 存储分配失败 */ L->elem = newbase; /* 新基址 */ L->listsize += LIST_INCREMENT;/* 增加存储容量 */ } q = L->elem + i - 1; /* q为插入位置 */ for(p = L->elem + L->length -1; p >= q; --p) /* 插入位置之后的元素后移 */ *(p+1) = *p; *q = e; /* 插入e */ ++L->length; /* 表增长1 */ return OK;}
/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) *//* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */Status ListDelete(SqList *L, int i, ElemType *e){ ElemType *p, *q; if(i < 1 || i > L->length) /* i值不合法 */ return ERROR; p = L->elem + i -1; /* p为被删除元素的位置 */ *e = *p; /* 被删除元素的值赋给e */ q = L->elem + L->length -1; /* 表尾元素位置 */ for(++p; p <= q; ++p) /* 被删除元素之后的元素左移 */ *(p-1) = *p; L->length--; /* 表长减1 */ return OK;}
/* 初始条件:顺序线性表L已存在 *//* 操作结果:依次对L的每个数据元素调用函数vi() *//* vi()的形参加'&',表明可通过调用vi()改变元素的值 */
void ListTraverse(SqList L, void(*vi)(ElemType *)){ ElemType *p; int i; p = L.elem; for(i=1; i <= L.length; i++) vi(p++); printf("\n");}
----------------------------------------------------------------------------------------华丽的分割线----------------------------------------------------------------------------------------------------------------------------
1、线性结构之线性表
线性表是这样一种结构,它包含n(n>=0)个数据元素,每个数据元素成为线性表的结点;其中a[0],a[1],a[2]......,a[n-1]组成的有限序列。
数据元素的个数n称为线性表的长度 = list.length(),当长度为空时,成为空表。
将非空的(n>0)线性表表示为:a[0],a[1],a[2]......,a[n-1].
其中数据元素a[i]只是一个抽象符号,具体元素是什么类型要看具体的情况。
一个数据元素并不要求是原子的,可以有若干数据项组成。每个数据元素成为记录,含有大量记录的线性表又称为文件。这种结构必须具有以下特点:存在一个唯一的没有前驱的(头)数据元素;存在一个唯一的没有后继的(尾)数据元素;此外,每一个数据元素均有一个直接前驱和一个直接后继数据元素。
2、线性表的存储结构
2.1 顺序表
顺序表在计算机内存中是以数组的形式保存的线性表,是用一组地址连续的存储单元依次存储数据元素的线性结构。下面介绍顺序表的C语言实现。
/** @function the basic operation on List* @author lz* @date 2013.8.18*/
//线性表的动态分配存储结构#define LIST_INIT_SIZE 10 /* 线性表存储空间的初始分配量 */#define LIST_INCREMENT 2 /* 线性表存储空间的分配增量 */typedef struct { ElemType *elem; /* 存储空间基址 */ int length; /* 当前长度 */ int listsize; /* 当前分配的存储容量(以sizeof(ElemType)为单位) */}SqList;
//基本操作
/* 顺序表示的线性表的基本操作(12个) */void InitList(SqList *L){ /* 操作结果: 构造一个空的顺序线性表L */ L->elem = malloc(LIST_INIT_SIZE*sizeof(ElemType)); if(!L->elem) exit(1);/* 存储分配失败 */ L->length = 0; /* 空表长度为0 */ L->listsize = LIST_INIT_SIZE; /* 初始存储容量 */}
/* 初始条件:顺序线性表L已经存在.操作结果:销毁线性表L */void DestroyList(SqList *L){ free(L->elem); L->elem = NULL; L->length = 0; L->listsize = 0;}
/* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */void ClearList(SqList *L){ L->length = 0;}
/* 初始条件:顺序线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */Status ListEmpty(SqList L){ if(L.length == 0) return TRUE; else return FALSE;}
/* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数 */int ListLength(SqList L){ return L.length;}
/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L)。操作结果:用e返回L中第i个数据元素的值 */Status GetElem(SqList L, int i, ElemType *e){ if(i < 1 || i > L.length) return ERROR; *e = (L.elem + i - 1); return OK;}
/* 初始条件:顺序线性表L已存在,compare()是数据元素判定函数(满足为1,否则为0) *//* 操作结果:返回L中第1个与e满足关系compare()的数据元素的位序。 *//* 若这样的数据元素不存在,则返回值为0。 */int LocateElem(SqList L, ElemType e, Status(*compare)(ElemType,ElemType)){ ElemType *p; int i = 1; /* i的初始值为第一个元素的位置 */ p = L.elem; /* p的初始值为第一个元素的存储位置 */ while(i <= L.length && !compare(*p++,e)) ++i; if(i <= L.length) return i; else return 0;}
/* 初始条件:顺序线性表L已存在 *//* 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱, *//* 否则操作失败,pre_e无定义 */Status PriorElem(SqList L, ElemType cur_e, ElemType *pre_e){ int i = 2; ElemType *p = L.elem + 1; while(i <= L.length && *p != cur_e) { /*?为什么前面使用函数指针,但是此却却直接使用值比较呢?*/ p++; i++; } if(i > L.length) return INFEASIBLE; /* 操作失败 */ else { *pre_e = *--p; return OK; }}
/* 初始条件:顺序线性表L已存在 *//* 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继, *//* 否则操作失败,next_e无定义 */Status NextElem(SqList L, ElemType cur_e, ElemType *next_e){ int i = 1; ElemType *p = L.elem; while(i < L.length && *p != cur_e) { i++; p++: } if(i == L.length) return INFEASIBLE; /* 操作失败 */ else { *next_e = *++p; return OK; }}
/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L)+1 *//* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */Status ListInsert(SqList *L, int i, ElemType e){ ElemType *newbase, *p, *q; if(i < 1 || i > L->length + 1) /* i值不合法 */ return ERROR; if(L->length >= L->listsize) /* 当前存储空间已满,增加存储分配 */ { newbase = realloc(L->elem, (L->listsize + LIST_INCREMENT)*sizeof(ElemType)); if(!newbase) exit(1); /* 存储分配失败 */ L->elem = newbase; /* 新基址 */ L->listsize += LIST_INCREMENT;/* 增加存储容量 */ } q = L->elem + i - 1; /* q为插入位置 */ for(p = L->elem + L->length -1; p >= q; --p) /* 插入位置之后的元素后移 */ *(p+1) = *p; *q = e; /* 插入e */ ++L->length; /* 表增长1 */ return OK;}
/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) *//* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */Status ListDelete(SqList *L, int i, ElemType *e){ ElemType *p, *q; if(i < 1 || i > L->length) /* i值不合法 */ return ERROR; p = L->elem + i -1; /* p为被删除元素的位置 */ *e = *p; /* 被删除元素的值赋给e */ q = L->elem + L->length -1; /* 表尾元素位置 */ for(++p; p <= q; ++p) /* 被删除元素之后的元素左移 */ *(p-1) = *p; L->length--; /* 表长减1 */ return OK;}
/* 初始条件:顺序线性表L已存在 *//* 操作结果:依次对L的每个数据元素调用函数vi() *//* vi()的形参加'&',表明可通过调用vi()改变元素的值 */
void ListTraverse(SqList L, void(*vi)(ElemType *)){ ElemType *p; int i; p = L.elem; for(i=1; i <= L.length; i++) vi(p++); printf("\n");}
----------------------------------------------------------------------------------------华丽的分割线----------------------------------------------------------------------------------------------------------------------------
相关文章推荐
- 数据结构—Problem D: 顺序表基本运算(线性表)
- C++数据结构之线性顺序表基本操作
- Java数据结构-线性表之顺序表ArrayList
- 数据结构 - 2顺序表及链表基本运算实现
- 数据结构中线性顺序表的基本操作(增删改查及合并)
- 线性数据结构--顺序表
- 数据结构(1)线性表中的顺序表
- 基本线性数据结构的Python实现
- 线性代数 1:基本的数据类型和数据结构选择
- 【源代码】C++实现严蔚敏数据结构所有算法(一)线性表-顺序表
- 《数据结构》实验二:线性表的实验 【顺序表】
- c/c++ 数据结构-线性表(单链表基本操作的实现)
- 数据结构类型定义及基本操作汇总(一)--线性表,单链表,栈和队列
- 基本数据结构----顺序表
- 基本数据结构:顺序表
- 基本数据结构(线性表)
- 【数据结构】 线性表的顺序表
- 基本数据结构(C#实现):顺序表
- 数据结构中之线性表中单链表的基本操作
- Problem C: 顺序表基本运算(线性表)