第二章 线性表
2017-09-14 22:34
288 查看
顺序表
Microsoft Visual Studio 2012实现:头文件:顺序表基本操作函数.h
源文件:顺序表.cpp
顺序表基本操作函数.h #include<iostream> using namespace std; const int LIST_INIT_SIZE=100; const int LIST_INCREMENT=100; typedef struct{ int *elem; int len; int listsize; }sqlist; void error_message(char *s){ cout<<s<<endl; exit(1); } void increment(sqlist &L){ int *p=new int[L.listsize+LIST_INCREMENT]; if(p==nullptr)error_message("内存分配失败"); for(int i=0;i<L.len;i++)p[i]=L.elem[i]; delete[]L.elem; L.elem=p; L.listsize+=LIST_INCREMENT; delete[] p; p=nullptr; } void init_sqlist(sqlist &L){ L.elem=new int[LIST_INIT_SIZE]; L.len=0; L.listsize=LIST_INIT_SIZE; } int locate_elem_sq(sqlist L,int e){ int i;//i表示位置,从1开始 for(i=1;i<=L.len && L.elem[i-1]!=e;++i); if(i<=L.len)return i; return 0; } //插入第i个元素之前,i从1开始 void insert_sqlist(sqlist &L,int i,int e){ if(i<1 || i>L.len+1)error_message("i值非法"); if(L.len>=L.listsize)increment(L); for(int j=L.len-1;j>=i-1;j--) L.elem[j+1]=L.elem[j]; L.elem[i-1]=e; L.len++; } void delete_sqlist(sqlist &L,int i,int &e){ if(i<1 || i>L.len)error_message("i值非法"); e=L.elem[i-1]; for(int j=i;j<L.len;j++) L.elem[j-1]=L.elem[j]; L.len--; } void destroy_sqlist(sqlist &L){ delete[] L.elem; L.elem=nullptr; L.len=0; L.listsize=0; }
顺序表.cpp #include<iostream> #include<cstdlib> #include"顺序表基本操作函数.h" using namespace std; void print(sqlist L){ for(int i=0;i<L.len;i++){ if(i==0)cout<<L.elem[i]; else cout<<" "<<L.elem[i]; } cout<<endl; } //例2.1已知两个集合A,B,求A=AUB void _union(sqlist &A,sqlist &B){ for(int i=0;i<B.len;i++){ if(!locate_elem_sq(A,B.elem[i])) insert_sqlist(A,A.len+1,B.elem[i]); } } //例2.2把非纯集合C的纯集合用D表示 void purify_set(sqlist &A,sqlist &B){ int cnt=1; for(int i=0;i<A.len;i++){ if(!locate_elem_sq(B,A.elem[i])) insert_sqlist(B,cnt++,A.elem[i]); } } //例2.3判断A,B两个集合是否相等 bool isequal(sqlist A,sqlist B){ if(A.len!=B.len)return false; sqlist C; init_sqlist(C); for(int i=0;i<A.len;i++) insert_sqlist(C,i+1,A.elem[i]); bool flag=true; for(int i=0;i<B.len;i++){ int loc=locate_elem_sq(C,B.elem[i]); if(loc){ int tmp; delete_sqlist(C,loc,tmp); } else{ flag=0; break; } } if(C.len==0 && flag){ destroy_sqlist(C); return true; } else{ destroy_sqlist(C); return false; } } //例2.4比较两个集合的字典序大小,类似于字符串大小比较,A>B返回1,A=B返回0,A<B返回-1 int compare(sqlist A,sqlist B){ for(int i=0;i<A.len && i<B.len;i++){ if(A.elem[i]>B.elem[i])return 1; else if(A.elem[i]<B.elem[i])return -1; } if(A.len>B.len)return 1; else if(A.len==B.len)return 0; else return -1; } //例2.5交换E(E1,E2,E3,E4)两个序列的位置,(1,2,)(3,4,5)变为(3,4,5,)(1,2) //例2.5(方案一) void exchange1(sqlist &A,int m,int n){ int *p=new int[m+n+5]; if(p==nullptr)error_message("内存分配失败"); int cnt=0; for(int i=m;i<m+n;i++) p[cnt++]=A.elem[i]; for(int i=0;i<m;i++) p[cnt++]=A.elem[i]; for(int i=0;i<A.len;i++){ A.elem[i]=p[i]; } delete[] p; p=nullptr; } //例2.5(方案二)先写右移一位的函数,再执行n次,达到效果 void right_move(sqlist &A){ int tmp=A.elem[A.len-1]; for(int i=A.len-2;i>=0;i--) A.elem[i+1]=A.elem[i]; A.elem[0]=tmp; } void exchange2(sqlist &A,int m,int n){ for(int i=0;i<n;i++) right_move(A); } //例2.5(方案三)一步到位右移n位 void exchange3(sqlist &A,int m,int n){ int *p=new int[m+n+5]; if(!p)error_message("内存分配失败"); for(int i=0;i<A.len;i++) p[(i+n)%(m+n)]=A.elem[i]; int tmp; while(A.len){ delete_sqlist(A,A.len,tmp); } for(int i=1;i<=m+n;i++) insert_sqlist(A,i,p[i-1]); delete[] p;p=nullptr; } //例2.5(方案四)逆置三次(类似于第一章 解题指导与示例7的方案四算法) void invert(sqlist &A,int i,int j){ for(int k=i;k<=(i+j)/2;k++) swap(A.elem[i+j-k],A.elem[k]); } void exchange4(sqlist &A,int m,int n){ invert(A,0,m-1); invert(A,m,m+n-1); invert(A,0,m+n-1); } //把两个非减表合并为一个非减表 void merge_sqlist(sqlist L1,sqlist L2,sqlist &L){ int i=0,j=0; int cnt=1; while(i<L1.len && j<L2.len){ if(L1.elem[i]<L2.elem[j]){ insert_sqlist(L,cnt++,L1.elem[i++]); } else{ insert_sqlist(L,cnt++,L2.elem[j++]); } } while(i<L1.len)insert_sqlist(L,cnt++,L1.elem[i++]); while(j<L2.len)insert_sqlist(L,cnt++,L2.elem[j++]); } //向有序表(非减)中插入元素后,仍然有序 void sqlist_insert_order(sqlist &L,int e){ int i=L.len-1; while(i>=0 && e<L.elem[i]){ L.elem[i+1]=L.elem[i]; i--; } L.elem[i+1]=e; L.len++; } //将有序顺序表中重复的元素,保留一个,其余删除 void sqlist_purify(sqlist &L){ int i=-1,j=0; while(j<L.len){ if(j==0 || L.elem[i]!=L.elem[j]) L.elem[++i]=L.elem[j]; j++; } L.len=i+1; } //筛选顺序表中的非负数 void sqlist_filter(sqlist &L){ int i=0,j=0; for(;i<L.len;i++){ if(L.elem[i]>=0){ if(i!=j) L.elem[j]=L.elem[i]; j++; } } L.len=j; } //删除线性表中第i个元素起的k个元素 void sqlist_delete_k(sqlist &L,int i,int k){ if(!(i>=1 && i<=L.len && k>=0 && i-1+k<=L.len)) error_message("删除元素的位置或者个数错误"); int e; while(k--){ delete_sqlist(L,i,e); } } int main() { int a[5]={1,2,3}; int b[5]={4,5}; int c[10]={1,2,2,3,4,5,5,6,7,7}; sqlist A,B,C,D,E1,E2,E3,E4,F,G; init_sqlist(A); init_sqlist(B); init_sqlist(C); init_sqlist(D); init_sqlist(E1);init_sqlist(E2);init_sqlist(E3);init_sqlist(E4); init_sqlist(F); init_sqlist(G); for(int i=1;i<=3;i++)insert_sqlist(A,i,a[i-1]); for(int i=1;i<=2;i++)insert_sqlist(B,i,b[i-1]); for(int i=1;i<=10;i++)insert_sqlist(C,i,c[i-1]); for(int i=1;i<=5;i++)insert_sqlist(E1,i,i); for(int i=1;i<=5;i++)insert_sqlist(E2,i,i); for(int i=1;i<=5;i++)insert_sqlist(E3,i,i); for(int i=1;i<=5;i++)insert_sqlist(E4,i,i); for(int i=1;i<=3;i++)insert_sqlist(F,i,i+2); //例2.1求两个集合的并集 cout<<"A: ";print(A); cout<<"B: ";print(B); _union(A,B); cout<<"A(AUB): "; print(A); cout<<endl; //例2.2把非纯集合C的纯集合用集合D表示 cout<<"C(非纯集合): ";print(C); purify_set(C,D); cout<<"D(C的纯集合): "; print(D); cout<<endl; //例2.3判断A,B两个集合是否相同 cout<<"A"<<(isequal(A,B)?"=":"!=")<<"B"<<endl; cout<<"B"<<(isequal(B,B)?"=":"!=")<<"B"<<endl; cout<<endl; //例2.4比较A,C两个集合字典序的大小,类似于字符串比较大小 int tmp=compare(A,C); if(tmp==1)cout<<"A>C"<<endl; else if(tmp==0)cout<<"A=C"<<endl; else cout<<"A<C"<<endl; cout<<endl; //例2.5交换E(E1,E2,E3,E4)两个序列的位置,(1,2,)(3,4,5)变为(3,4,5,)(1,2) //例2.5(方案一) exchange1(E1,2,3); print(E1); //例2.5(方案二) exchange2(E2,2,3); print(E2); //例2.5(方案三)一步到位右移n位 exchange3(E3,2,3); print(E3); //例2.5(方案四)逆置三次(类似于第一章 解题指导与示例7的方案四算法) exchange4(E4,2,3); print(E4); cout<<endl; //把两个有序的顺序表B,F合并成一个有序的顺序表G cout<<"B,F有序合并:"<<endl; merge_sqlist(B,F,G); cout<<"G: "; print(G); //G中插入2,仍然有序 cout<<"G中插入2,仍然有序"<<endl; cout<<"G: "; sqlist_insert_order(G,2); print(G); //去除G中的重复元素 cout<<"把G净化为集合,G: "; sqlist_purify(G); print(G); //G中插入几个负数 for(int i=5;i<=8;i++) insert_sqlist(G,i,i-100); cout<<"G插入几个负数后,G:"; print(G); cout<<"筛出G中的负数后,G:"; sqlist_filter(G); print(G); //删除G中第2个元素开始的2个元素 cout<<"删除G中第2个元素开始的2个元素后,G: "; sqlist_delete_k(G,2,2); print(G); }
链表
Microsoft Visual Studio 2012实现:头文件:链表.h
源文件:链表.cpp
输入方式:重定向,文件内容如下,
5 4 3 2 1
1 2 3 3 3 4 5
7 8 9
12 13 14 15 16 17
链表.h #include<iostream> #include<string> using namespace std; typedef int elemtype; typedef struct Node{ elemtype data; struct Node *next; }node,*linklist; //定义双向链表类型 typedef struct dnode{ elemtype data; struct dnode *prior,*next; }dnode,*dlinklist; //错误提示函数 void error_message(string s){ cout<<s<<endl; exit(-1); } //头插法建立链表 void create_linklist1(linklist &L,int n){ L=new node; if(L==nullptr)error_message("分配内存失败"); L->next=nullptr; for(int i=0;i<n;i++){ node *p=new node; if(p==nullptr)error_message("分配内存失败"); cin>>p->data; p->next=L->next;L->next=p; } } //尾插法建立链表 void create_linklist2(linklist &L,int n){ L=new node; if(L==nullptr)error_message("分配内存失败"); L->next=nullptr; node *rear=L; for(int i=0;i<n;i++){ node *p=new node; if(p==nullptr)error_message("分配内存失败"); p->next=nullptr;//忘记写这句,程序崩溃! cin>>p->data; rear->next=p; rear=p;//rear始终指向链表的最后一个节点 } } //尾插法建立双向循环链表 void create_dlinklist2(dlinklist &L,int n){ L=new dnode; if(L==nullptr) error_message("分配内存失败"); L->next=nullptr; L->prior=nullptr; dnode *rear=L; for(int i=0;i<n;i++){ dnode *p=new dnode; if(p==nullptr) error_message("分配内存失败"); cin>>p->data; p->next=nullptr; p->prior=rear; rear->next=p; rear=p; } rear->next=L; } //销毁链表 void linklist_destroy(linklist &L){ node *p=nullptr,*head=L->next; while(head){ p=head->next; delete head; head=p; } } //清空链表 void linklist_clear(linklist &L){ node *p=L->next; node *q=nullptr; while(p){ q=p->next; delete p; p=q; } L->next=nullptr; } //遍历链表,输出所有数据值 void linklist_traverse(linklist L){ node *p=L->next; while(p!=nullptr){ cout<<p->data<<" "; p=p->next; } cout<<endl; } //遍历双向链表,输出所有数据值 void dlinklist_traverse(dlinklist L,int n){ dnode *p=L->next; int i=0; while(p!=nullptr && i<n){ cout<<p->data<<" "; p=p->next; i++; } cout<<endl; } //求链表长度 int linklist_length(linklist L){ node *p=L->next; int cnt=0; while(p!=nullptr){ cnt++; p=p->next; } return cnt; } //查找链表中第i个元素,并存放在e中 bool get_elem(linklist L,int i,elemtype &e){ if(i<1 || i>linklist_length(L))return false; node *p=L; while(i--){ p=p->next; } e=p->data; return true; } //查找链表中第一个与e相等的节点的位置 int locate_elem(linklist L,elemtype e){ int i=1; node *p=L->next; while(p!=nullptr && p->data!=e){ i++; p=p->next; } if(p!=nullptr)return i; else return 0; } //查找链表中与e相等的节点的个数 int e_num(linklist L,elemtype e){ int cnt=0; node *p=L->next; while(p){ if(p->data==e)cnt++; p=p->next; } return cnt; } //在链表的第i个元素之前插入新节点 void linklist_insert(linklist &L,int i,elemtype e){ node *pi=L; int j=0; while(pi && j<i-1){ j++; pi=pi->next; } if(!pi || j>i-1){ //若pi=nullptr,则插入节点的位置大于了链表的长度加1,j>i-1,则i<=1 //i=1,表明插入第一个位置,i<1,表明插入位置不存在 error_message("插入位置不存在"); } node *p=new node; if(p==nullptr)error_message("内存分配失败"); p->data=e; p->next=pi->next; pi->next=p; } //双向链表的第i个元素之前插入新节点 void dlinklist_insert(dlinklist &L,int i,elemtype e){ dnode *pi=L; int j=0; while(pi && j<i-1){ j++; pi=pi->next; } if(!pi || j>i-1){ error_message("插入位置不存在"); } dnode *p=new dnode; if(p==nullptr) error_message("内存分配失败"); p->data=e; p->next=pi->next; p->prior=pi; pi->next->prior=p; pi->next=p; } //逆置链表 void linklist_reverse(linklist &L){ node *p=L->next; node *post=nullptr; node *pre=nullptr; while(p){ post=p->next; p->next=pre; pre=p; p=post; } L->next=pre; } //删除链表中第i个节点,保存在e中 void linklist_delete(linklist &L,int i,elemtype &e){ node *p=L; int j=0; while(p->next && j<i-1){ p=p->next; j++; } if(!p->next || j>i-1){ //若p->next=nullptr,则删除的节点要么不存在,要么是nullptr,j>i-1表明i<=0 error_message("要删除的元素位置错误"); } node *tmp=p->next; e=tmp->data; p->next=tmp->next; delete tmp; } //删除链表中的偶数序号的结点 void linklist_delete_even(linklist &L){ node *p=L->next; node *q=nullptr; while(p && p->next){ q=p->next; p->next=q->next; p=q->next; delete q; } } //删除双向循环链表中的第i个元素,保存在e中 void dlinklist_delete(dlinklist &L,int i,elemtype &e){ dnode *p=L; int j=0; while(p->next && j<i){ p=p->next; j++; } if(!p || j>i){ error_message("要删除的元素位置错误"); } e=p->data; p->prior->next=p->next; p->next->prior=p->prior; delete p; } //两个有序链表合并成一个有序表 void linklist_merge(linklist L1,linklist L2,linklist &L3){ L3=new node; if(L3==nullptr) error_message("内存分配失败"); L3->next=nullptr; node *p1=L1->next; node *p2=L2->next; node *rear=L3; while(p1 && p2){ if(p1->data < p2->data){ node *tmp=new node; if(tmp==nullptr) error_message("内存分配失败"); tmp->next=nullptr; tmp->data=p1->data; rear->next=tmp; rear=tmp; p1=p1->next; } else{ node *tmp=new node; if(tmp==nullptr) error_message("内存分配失败"); tmp->next=nullptr; tmp->data=p2->data; rear->next=tmp; rear=tmp; p2=p2->next; } } while(p1){ node *tmp=new node; if(tmp==nullptr) error_message("内存分配失败"); tmp->next=nullptr; tmp->data=p1->data; rear->next=tmp; rear=tmp; p1=p1->next; } while(p2){ node *tmp=new node; if(tmp==nullptr) error_message("内存分配失败"); tmp->next=nullptr; tmp->data=p2->data; rear->next=tmp; rear=tmp; p2=p2->next; } } //链表求两个集合A,B的并集A=AUB void linklist_union(linklist &A,linklist B){ //求A的最后一个节点的地址pre,最后用rear11表示 node *rear11=A->next; node *pre=A; while(rear11){ pre=pre->next; rear11=rear11->next; } rear11=pre; node *rear2=B->next; while(rear2){ bool flag=false; node *rear1=A->next; while(rear1){ if(rear1->data==rear2->data){ flag=true; break; } rear1=rear1->next; } if(!flag){ node *tmp=new node; if(tmp==nullptr)error_message("内存分配失败"); tmp->next=nullptr; tmp->data=rear2->data; rear11->next=tmp; rear11=tmp; } rear2=rear2->next; } } //把链表改成单循环链表 void to_circle_linklist(linklist &L){ node *p=L; while(p->next!=nullptr){ p=p->next; } p->next=L; } //合并两个链表 void linklist_combine(linklist &L1,linklist &L2){ node *p=L1; while(p->next!=nullptr){ p=p->next; } p->next=L2->next; }
链表.cpp //下面是一个链表基本操作的测试用的程序 //下面是一个链表基本操作的测试用的程序 #include<iostream> #include"链表.h" using namespace std; int main() { freopen("input.txt","r",stdin); linklist list1=nullptr; linklist list2=nullptr; linklist list3=nullptr; linklist list4=nullptr; dlinklist list5=nullptr; //头插法创建一个长度是5的链表:1,2,3,4,5 cout<<"下面头插法创建链表list1,请输入5,4,3,2,1"<<endl; create_linklist1(list1,5); cout<<"list1: "; linklist_traverse(list1);//输出链表 //尾插法创建一个长度为5的链表:1,2,3,3,3,4,5 cout<<"下面尾插法创建链表list2,请输入1,2,3,3,3,4,5"<<endl; create_linklist2(list2,7); cout<<"list2: "; linklist_traverse(list2); //尾插法创建链表list3: 7,8,9 create_linklist2(list3,3); cout<<"list3: "; linklist_traverse(list3); cout<<endl; //求链表长度 cout<<"list1的长度是"<<linklist_length(list1)<<endl; //查找 elemtype e1; get_elem(list1,5,e1); cout<<"list1中第5个元素是"<<e1<<endl; cout<<endl; cout<<"list2中第1个3的位置是"<<locate_elem(list2,3)<<endl; cout<<"list2中与3相等的节点的个数是"<<e_num(list2,3)<<endl; //插入 cout<<"list2中第4个节点之前插入6后的list2: "<<endl; linklist_insert(list2,4,6); linklist_traverse(list2); //逆置链表 cout<<"list2逆置后:"; linklist_reverse(list2); linklist_traverse(list2); //删除操作 elemtype e2; linklist_delete(list2,2,e2); cout<<"删除list2的第2个元素"<<e2<<"后,list2: "; linklist_traverse(list2); cout<<endl; //两个有序表合并成一个有序表 cout<<"list1和list3合并为list4: "; linklist_merge(list1,list3,list4); linklist_traverse(list4); cout<<endl; //求两个集合A,B的并集A(A=AUB) linklist_union(list1,list3); cout<<"list1,list3两个集合的并集为list1(list1 U list3):"; linklist_traverse(list1); cout<<endl; cout<<"***************************************************************************"<<endl; cout<<"目前四个链表如下"<<endl; cout<<"list1:";linklist_traverse(list1); cout<<"list2:";linklist_traverse(list2); cout<<"list3:";linklist_traverse(list3); cout<<"list4:";linklist_traverse(list4); cout<<endl; //把list1,list2改成单循环链表,并合并成一个链表 cout<<"list1,list2合并成list1"<<endl; linklist_combine(list1,list2); cout<<"list1:";linklist_traverse(list1); cout<<endl; //建立双向链表list5:12,13,14,15,16,17 cout<<"创建双向循环链表list5"<<endl; create_dlinklist2(list5,6); cout<<"list5:"; dlinklist_traverse(list5,6); cout<<endl; //双向循环链表list5的第3个元素之前插入666 cout<<"list5的第3个元素之前插入666"<<endl; dlinklist_insert(list5,3,666); cout<<"list5: "; dlinklist_traverse(list5,7); cout<<endl; //双向循环链表list5删除第4个元素 elemtype e3; dlinklist_delete(list5,4,e3); cout<<"删除list5中的第4个元素"<<e3<<"后,list5: "; dlinklist_traverse(list5,6); cout<<endl; //删除list1中偶数序号结点 cout<<"删除偶数序号结点后,list1: "; linklist_delete_even(list1); linklist_traverse(list1); return 0; }
相关文章推荐
- 《数据结构》第二章线性表设计2:同学博客中问题求解
- 第二章 线性表 思维导图
- 第二章:线性表
- <数据结构> 第二章 线性表之循环链表的代码粗实现
- 第二章 习题2.1-3 查找线性表
- 数据结构 第二章 线性表(4)单链表的实现
- <数据结构> 第二章 线性表 思维导图
- 全面精讲解读C++数据结构第二章线性表c++版
- 第二章:线性表
- 《线性表》第二章知识导图
- 数据结构复习——第二章:线性表
- 数据结构编程笔记四:第二章 线性表 单链表的实现
- 第二章 习题2.1-3 查找线性表
- 第二章 线性表 知识导图
- 数据结构 第二章 线性表 英语成绩表的顺序表实现
- 《数据结构(C++版)》之第二章线性表
- Leetcode 第二章线性表--2.2 单链表--2.2.1 add two numbers--2017/7/25
- 第二章 习题2.1-3 查找线性表
- [数据结构]第二章--线性表(读书笔记1)
- 第二章 线性表