您的位置:首页 > 其它

第二章 线性表

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: