标签:
线性表(linear_list)是最常用且最简单的一种数据结构。
一个线性表是n个数据元素的有限序列,它有两种表示形式:顺序表示跟链式表示。
线性表的顺序表示和实现
线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素,这种数据结构称之为顺序表。
下面顺序表的一种实现
1 #include <stdio.h> 2 #include <malloc.h> 3 #include <stdbool.h> 4 #define OK 1 5 #define ERROR 0 6 #define OVERFLOW -1 7 #define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量 8 #define LISTINCREMENT 10 //线性表存储空间的分配增量 9 10 typedef char ElemType; 11 typedef struct 12 { 13 ElemType *elem; //存储空间的基址 14 int length; //当前长度 15 int listsize; //当前分配的存储容量(以sizeof(ElemType)为单位) 16 }SqList; 17 18 //初始化顺序表 19 int InitList(SqList &L) 20 { 21 L.elem=(ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType)); 22 if(!L.elem) return OVERFLOW; //存储分配失败 23 L.length=0; //空表长度为0 24 L.listsize=LIST_INIT_SIZE; //初始存储容量 25 return OK; 26 } 27 28 //销毁顺序表 29 void DestroyList(SqList &L) 30 { 31 free(L.elem); 32 } 33 34 //在顺序表L中第i个位置之前插入新的元素e 35 int ListInsert(SqList &L,int i,ElemType e) 36 { 37 //i的合法值为1≤i≤L.length+1 38 if(i<1||i>L.length+1) return ERROR; 39 //当前存储空间已满,重新分配空间 40 if(L.length>=L.listsize) 41 { 42 ElemType *newbase=NULL; 43 newbase=(ElemType *)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(ElemType)); 44 if(!newbase) return OVERFLOW; 45 L.elem=newbase; 46 L.listsize+=LISTINCREMENT; 47 } 48 //p为插入位置 49 ElemType *p=&(L.elem[i-1]); 50 //插入位置及之后的元素右移 q为最后一个元素的位置 51 for(ElemType *q=(L.elem+L.length-1);q>=p;--q) *(q+1)=*q; 52 *p=e; //插入e 53 ++L.length; //表长加1 54 } 55 56 //在顺序表L中删除第i个元素,并用e返回其值 57 int ListDelete(SqList &L,int i,ElemType &e) 58 { 59 //i的合法值为1≤i≤L.length 60 if(i<1||i>L.length) return ERROR; 61 ElemType *p=&(L.elem[i-1]); //p为被删除位置元素的位置 62 e=*p; //将删除元素的值赋给e 63 ElemType *q=L.elem+L.length-1; //q为表尾元素的位置 64 for(;p<=q;++p) *p=*(p+1); 65 --L.length; 66 return OK; 67 } 68 69 70 //判断顺序表是否为空表 71 bool ListEmpty(SqList &L) 72 { 73 return (L.length==0); 74 } 75 76 //求顺序表的长度 77 int ListLength(SqList &L) 78 { 79 return (L.length); 80 } 81 82 //输出顺序表 83 void DispList(SqList &L) 84 { 85 if(ListEmpty(L)) return; 86 for(int i=0;i<L.length;++i) 87 printf("%c",L.elem[i]); 88 printf("\n"); 89 } 90 91 //获取顺序表中索引位置的元素值 92 bool GetElem(SqList &L,int i,ElemType &e) 93 { 94 if(i<1||i>L.length) return false; 95 e=L.elem[i-1]; 96 return true; 97 } 98 99 //按元素值查找 100 int LocateElem(SqList &L,ElemType e) 101 { 102 int i=0; 103 //查找元素e 104 while(i<L.length&&L.elem[i++]!=e); 105 //未找到 106 if(i>L.length) return -1; 107 return i; 108 }
线性表的链式表示和实现
线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。
为了表示元素之间的逻辑(先后)关系,对于任一数据元素,除了存储元素本身的信息之外,还需存储一个指示其直接后继的信息(即直接后继的存储位置)。
每个数据元素包含两个域:其中存储数据元素信息的域称为数据域,存储直接后继存储位置的域称为指针域。
下面是单链表(带头节点)的一种实现
1 #include <stdio.h> 2 #include <malloc.h> 3 typedef char ElemType; 4 //定义单链表节点类型 5 typedef struct LNode 6 { 7 ElemType data; 8 struct LNode *next; 9 }LinkList; 10 11 //初始化 12 void InitList(LinkList *&L) 13 { 14 //创建头节点 15 L=(LinkList *)malloc(sizeof(LinkList)); 16 L->next=NULL; 17 } 18 19 //销毁单链表 20 void DestroyList(LinkList *&L) 21 { 22 LNode *p=L; 23 LNode *q=p->next; 24 while(q!=NULL) 25 { 26 free(p); 27 p=q; 28 q=q->next; 29 } 30 free(p); 31 } 32 33 //判断是否为空表 34 bool ListEmpty(LinkList *L) 35 { 36 return (L->next==NULL); 37 } 38 39 //求单链表的长度 40 int ListLength(LinkList *L) 41 { 42 int i=0; 43 LNode *p=L; 44 while(p->next!=NULL) 45 { 46 i++; 47 p=p->next; 48 } 49 return i; 50 } 51 52 //输出单链表 53 void DispList(LinkList *L) 54 { 55 LNode *p=L->next; 56 while(p!=NULL) 57 { 58 printf("%c",p->data); 59 p=p->next; 60 } 61 printf("\n"); 62 } 63 64 //按逻辑索引值找数据元素值 该值通过e返回 65 bool GetElem(LinkList *L,int i,ElemType &e) 66 { 67 int j=0; 68 LNode *p=L; 69 while(j<i&&p!=NULL) 70 { 71 j++; 72 p=p->next; 73 } 74 if(p==NULL) 75 return false; 76 e=p->data; 77 return true; 78 } 79 80 //按元素值查找逻辑索引值 81 int LocateElem(LinkList *L,ElemType e) 82 { 83 LNode *p=L->next; 84 int i=1; 85 while(p!=NULL&&p->data!=e) 86 { 87 i++; 88 p=p->next; 89 } 90 if(p==NULL) 91 return 0; 92 return i; 93 } 94 95 //插入数据元素 96 bool ListInsert(LinkList *&L,int i,ElemType e) 97 { 98 int j=0; 99 LNode *p=L; 100 //找到索引为i-1的节点 101 while(j<i-1&&p!=NULL) 102 { 103 j++; 104 p=p->next; 105 } 106 if(p==NULL) 107 return false; 108 LNode *node=(LNode *)malloc(sizeof(LNode)); 109 node->data=e; 110 node->next=p->next; 111 p->next=node; 112 return true; 113 } 114 115 //删除数据元素 116 bool ListDelete(LinkList *&L,int i,ElemType &e) 117 { 118 int j=0; 119 LNode *p=L; 120 //找到索引为i-1的节点 121 while(j<i-1&&p!=NULL) 122 { 123 j++; 124 p=p->next; 125 } 126 //未找到第i-1个节点 127 if(p==NULL) 128 return false; 129 //不存在第i个节点 130 if(p->next==NULL) 131 return false; 132 //记录要删除的节点 133 LNode *q=p->next; 134 e=q->data; 135 p->next=q->next; 136 free(q); 137 return true; 138 }
双链表中的元素比单链表的元素多出一个指针域,这个指针域指向该元素的前驱。
双链表的实现跟单链表类似,只是多出了对前驱指针域的操作。
下面是双链表(带头节点)的一种实现(只给出与单链表不同的代码)
1 #include <stdio.h> 2 #include <malloc.h> 3 typedef char ElemType; 4 //定义双链表节点类型 5 typedef struct DNode 6 { 7 ElemType data; 8 struct DNode *prior; 9 struct DNode *next; 10 }DLinkList; 11 12 //初始化 13 void InitList(DLinkList *&L) 14 { 15 //创建头结点 16 L=(DLinkList *)malloc(sizeof(DLinkList)); 17 L->prior=L->next=NULL; 18 } 19 20 //插入数据元素 21 bool ListInsert(DLinkList *&L,int i,ElemType e) 22 { 23 int j=0; 24 DNode *p=L; 25 //找到索引为i-1的节点 26 while(j<i-1&&p!=NULL) 27 { 28 j++; 29 p=p->next; 30 } 31 if(p==NULL) 32 return false; 33 //将*node插入到*p之后 34 DNode *node=(DNode *)malloc(sizeof(DNode)); 35 node->data=e; 36 node->next=p->next; 37 //如果*p不是最后一个节点 38 if(p->next!=NULL) 39 p->next->prior=node; 40 p->next=node; 41 node->prior=p; 42 return true; 43 } 44 45 //删除数据元素 46 bool ListDelete(DLinkList *&L,int i,ElemType &e) 47 { 48 int j=0; 49 DNode *p=L; 50 //找到索引为i-1的节点 51 while(j<i-1&&p!=NULL) 52 { 53 j++; 54 p=p->next; 55 } 56 //未找到第i-1个节点 57 if(p==NULL) 58 return false; 59 //不存在第i个节点 60 if(p->next==NULL) 61 return false; 62 //删除*q节点 63 DNode *q=p->next; 64 e=q->data; 65 p->next=q->next; 66 //如果*q不是最后一个节点 67 if(q->next!=NULL) 68 q->next->prior=q->prior; 69 free(q); 70 return true; 71 }
循环链表是另一种形式的链式存储的结构,它的特点是表中最后一个节点的指针域指向头节点,整个链表形成一个环。
下图是一个循环单链表
下图是一个循环双链表
标签:
原文地址:http://www.cnblogs.com/runnyu/p/4702415.html