【数据结构】线性表常用操作(C++)
线性表
顺序表示
定义:
#define MAXSIZE 100 //最大长度 typedef struct { ElemType * elem; //指向线性表的基地址 int length; //线性表当前长度 }SqList;
相关函数:
C语言:<stdlib.h>
malloc(m)
开辟 m 字节长度的地址空间,并返回这段空间的首地址。
sizeof(x)
计算变量 x 的长度。
free(p)
释放指针 p 所指变量的存储空间,即彻底删除一个变量。
C++:new
int *p1 = new int; //或者 int *p1 = new int(10); //删除 delete p1;
初始化线性表
参数用引用
Status InitList_Sq(SqList &L) //构造一个空的顺序表L { L.elem = new ElemType[MAXSIZE]; //为顺序表分配空间 if(! L.elem) { exit(OVERFLOW); //存储分配失败 } L.length = 0; return OK; }
参数用指针
Status InitList_Sq(SqList *L) //构造一个空的顺序表L { L -> elem = new ElemType[MAXSIZE]; //为顺序表分配空间 if( ! L -> elem) { exit(OVERFLOW); //存储空间分配失败 } L -> length = 0; return OK; }
销毁线性表L
void DestroyList(SqList &L) { if(L.elem) { delete[] L.elem; //释放存储空间 } }
清空线性表L
void ClearList(SqList &L) { L.length = 0; //将线性表的长度置为 0 }
判断线性表L的长度
int GetLength(SqList L) { return (L.length); }
判断线性表L是否为空
int IsEmpty(SqList L) { if(L.length == 0) { return 1; } else { return 0; } }
取值(根据位置 i 获取相应位置数据元素的内容)
//获取线性表L中的某个数据元素的内容 int GetElem(SqList L,int i,ElemType &e) { if(i < 1 || i > length) { return ERROR; } //判断 i 值是否合理,若不合理,返回ERROR e = L.elem[i-1]; //第 i-1 的单眼存储着第 i 个数据 return OK; }
查找(根据指定数据获取数据所在的位置)
//在线性表 L 中查找值为 e 的数据元素 int LocateElem(SqList L,ElemType e) { for( i = 0; i < L.length; i++) { if(L.elem[i] == e) { return i+1; } } return 0; }
在线性表L中第i个元素之前插入数据元素e
Status ListInsert_Sq(SqList &L, int i, ElemType e) { int j; if(i<1 || i > L.length+1) { return RERROR; // i 值不合法 } if(L.length == MAXSIZE) { return ERROR; //当前存储空间已满。 } for( j=L.length-1; j >= i-1; j--) { L.elem[j+1] = L.elem[j]; //插入位置及之后的元素后移 L.elem[i-1] = e; //将新元素 e 放入第 i 个位置 ++L.length; //表长增1 return OK; } }
将线性表 L 中第 i 个元素删除
Status ListDelete_Sq(SqList &L, int i) { if( (i<1) || (i > L.length) ) { return ERROR; // i 值不合法 } for( j=i; j <= L.length-1; j++ ) { L.elem[j-1] = L.elem[j]; //被删除元素之后的元素前移 } --L.length; //表长减 1 return OK; }
链式表示
存储结构定义
typedef struct Lnode { ElemType data; //数据域 struct LNode *next; //指针域 } LNode,*LinkList; //*LinkList 为 Lnode 类型的指针
初始化
Struct InitList_L(LinkList &L) { L = new LNode; L -> next = NULL; return OK; }
销毁
Status DestroyList_L(LinkList &L) { LinkList p; while(L) { p = L; L = L -> next; delete p; } return OK; }
清空
Status ClearList(LinkList & L) { // 将L重置为空表 LinkList p,q; p = L-> next; //p指向第一个结点 while(p) //没到表尾 { q = p -> next; delete p; p = q; } L -> next = NULL; //头结点指针域为空 return OK; }
求表长
//返回L中数据元素个数 int ListLength_L(LinkList L) { LinkList p; p = L -> next; //p指向第一个结点 i=0; //遍历单链表,统计结点数 while(p) { i++; p=p->next; } return i; }
判断表是否为空
int ListEmpty(LinkList L) { //若L为空表,则返回1,否则返回0 if(L->next) { //非空 return 0; } else { return 1; } }
取值(根据位置i获取相应位置数据元素的内容)
//获取线性表L中的某个数据元素的内容 Status GetElem_L(LinkList L,int i,ElemType &e) { p = L -> next; j = 1; //初始化 while( p && j < i ) { //向后扫描,直到p指向第i个元素或p为空 p = p -> next; ++j; } if(!p || j>i) { //第i个元素不存在 return ERROR; } e = p -> data; //取第i个元素 return OK; }//GetElem_L
在线性表L中查找值为e的数据元素
LNode *LocateELem_L (LinkList L,Elemtype e) { //返回L中值为e的数据元素的地址,查找失败返回NULL p =L->next; while( p && p->data != e) { p=p->next; } return p; } int LocateELem_L (LinkList L,Elemtype e) { //返回L中值为e的数据元素的位置序号,查找失败返回0 p = L->next; j = 1; while(p && p->data != e) { p = p->next; j++; } if(p) { return j; } else { return 0; } }
在 L 中第 i 个元素之前插入数据元素e
Status ListInsert_L(LinkList &L,int i,ElemType e){ p=L; j=0; //寻找第i?1个结点 while( p && j < i?1 ) { p = p->next; ++j; } //i大于表长?+?1或者小于1 if(!p||j>i?1) { return ERROR; } s = new LNode; //生成新结点s s->data = e; //将结点s的数据域置为e s->next = p->next; //将结点s插入L中 p->next = s; return OK; }//ListInsert_L
将线性表L中第i个数据元素删除
Status ListDelete_L(LinkList &L,int i,ElemType &e){ p=L;j=0; while(p->next &&j<i-1){ //寻找第i个结点,并令p指向其前驱 p=p->next; ++j; } if(!(p->next)||j>i-1) return ERROR; //删除位置不合理 q=p->next; //临时保存被删结点的地址以备释放 p->next=q->next; //改变删除结点前驱结点的指针域 e=q->data; //保存删除结点的数据域 delete q; //释放删除结点的空间 return OK; }//ListDelete_L
单链表的建立(前插法)
void CreateList_F(LinkList &L,int n){ L=new LNode; L->next=NULL; //先建立一个带头结点的单链表 for(i=n;i>0;--i){ p=new LNode; //生成新结点 cin>>p->data; //输入元素值 p->next=L->next;L->next=p; //插入到表头 } }//CreateList_F
单链表的建立(尾插法)
void CreateList_L(LinkList &L,int n){ //正位序输入n个元素的值,建立带表头结点的单链表L L=new LNode; L->next=NULL; r=L; //尾指针r指向头结点 for(i=0;i<n;++i){ p=new LNode; //生成新结点 cin>>p->data; //输入元素值 p->next=NULL; r->next=p; //插入到表尾 r=p; //r指向新的尾结点 } }//CreateList_L
循环链表的合并
//假设 Ta、Tb 都是非空的单循环链表 LinkList Connect(LinkList Ta,LinkList Tb) { p = Ta -> next; // p 存表头结点 Ta->next = Tb->next->next; // Tb 表头连结 Ta 表尾 delete Tb->next; //释放 Tb 表头结点 Tb->next = p; //修改指针 return Tb; }
双向链表
typedef struct DuLNode{ ElemType data; struct DuLNode *prior; struct DuLNode *next; }DuLNode, *DuLinkList
双向链表的插入
Status ListInsert_DuL(DuLinkList &L,int i,ElemType e){ if(!(p=GetElemP_DuL(L,i))) return ERROR; s=new DuLNode; s->data=e; s->prior=p->prior; p->prior->next=s; s->next=p; p->prior=s; return OK; }
双向链表的删除
Status ListDelete_DuL(DuLinkList &L,int i,ElemType &e) { if(!(p=GetElemP_DuL(L,i))) return ERROR; e=p->data; p->prior->next=p->next; p->next->prior=p->prior; delete p; return OK; }
线性表的合并
void union(List &La, List Lb){ La_len=ListLength(La); Lb_len=ListLength(Lb); for(i=1;i<=Lb_len;i++){ GetElem(Lb,i,e); if(!LocateElem(La,e)) ListInsert(&La,++La_len,e); } } // O(ListLength(LB) x ListLength(LB))
有序的顺序表合并
void MergeList_Sq(SqList LA,SqList LB,SqList &LC){ pa=LA.elem; pb=LB.elem; //指针pa和pb的初值分别指向两个表的第一个元素 LC.length=LA.length+LB.length; //新表长度为待合并两表的长度之和 LC.elem=new ElemType[LC.length]; //为合并后的新表分配一个数组空间 pc=LC.elem; //指针pc指向新表的第一个元素 pa_last=LA.elem+LA.length-1; //指针pa_last指向LA表的最后一个元素 pb_last=LB.elem+LB.length-1; //指针pb_last指向LB表的最后一个元素 while(pa<=pa_last && pb<=pb_last){ //两个表都非空 if(*pa<=*pb) *pc++=*pa++; //依次“摘取”两表中值较小的结点 else *pc++=*pb++; } pa++; //LB表已到达表尾 while(pb<=pb_last) *pc+ while(pa<=pa_last) *pc++=*+=*pb++; //LA表已到达表尾 }//MergeList_Sq //T(n)= O(ListLength(LB) + ListLength(LB)) //S(n)= O(n)
有序的链表合并
void MergeList_L(LinkList &La,LinkList &Lb,LinkList &Lc){ pa=La->next; pb=Lb->next; pc=Lc=La; //用La的头结点作为Lc的头结点 while(pa && pb){ if(pa->data<=pb->data){ pc->next=pa;pc=pa;pa=pa->next;} else{pc->next=pb; pc=pb; pb=pb->next;} pc->next=pa?pa:pb; //插入剩余段 delete Lb; //释放Lb的头结点} } }