一、线性表及其顺序存储
ADT:
类型名称:线性表(List)
对象集:线性表是n个元素构成的有序序列
操作集:初始化,按值寻找,按序号寻找,插入,删除,求链表长
typedef struct LNode* List;
struct LNode
{
ElementType Data[MMAXSIZE];
int Last;
};
List Ptrl;代表整个线性表
#include<iostream>
using namespace std;
#define MaxSize 11
typedef struct LNode* List;
struct LNode
{
int arr[MaxSize];
int last;
};
List Ptrl;
//建立一个空表
List MakeEmpty()
{
Ptrl = new struct LNode;
Ptrl->last=-1;
return Ptrl;
}
//插入
void Insert(int X,int i,List Ptrl)
{
if(Ptrl->last==MaxSize-1)
{
cout << "表已满"<<endl;
return;
}
if(i<1||i>Ptrl->last+2)
{
cout << "输入的位置不合法"<<endl;
return;
}
for(int j=Ptrl->last;j>=i-1;j--)
{
Ptrl->arr[j+1]=Ptrl->arr[j];
}
Ptrl->arr[i-1]=X;//这个语句必须放后面,因为放前面会把插入的值移动到后面
Ptrl->last++;
return;
}
void Delete(int i,List Ptrl);
int Find(int X,List Ptrl);
int main()
{
MakeEmpty();
Insert(100,1,Ptrl);
Insert(200,2,Ptrl);
Insert(300,3,Ptrl);
Insert(400,4,Ptrl);
Insert(500,5,Ptrl);
Insert(600,6,Ptrl);
Insert(700,7,Ptrl);
Insert(800,8,Ptrl);
Insert(900,9,Ptrl);
Insert(1000,10,Ptrl);
Insert(23,2,Ptrl);//插入2号位置
cout << Ptrl->arr[0]<<endl;
cout << Ptrl->arr[1]<<endl;
cout << Ptrl->arr[2]<<endl;
cout << Ptrl->arr[3]<<endl;
cout << Ptrl->arr[4]<<endl;
cout << Ptrl->arr[5]<<endl;
cout << Ptrl->arr[6]<<endl;
cout << Ptrl->arr[7]<<endl;
cout << Ptrl->arr[8]<<endl;
cout << Ptrl->arr[9]<<endl;
cout << Ptrl->arr[10]<<endl;
Delete(2,Ptrl);//删除第二个位置的元素,200没了
cout << Ptrl->arr[1]<<endl;//第一位应该不变仍然是100
cout << Ptrl->arr[9]<<endl;//第9位应该是1000
cout << Ptrl->arr[10]<<endl;//第十位应该位NULL即0
cout << Find(1000,Ptrl) <<endl;//打印1000的位置应该是第9位,即换算成数组下标为10
}
//删除
void Delete(int i,List Ptrl)
{
if(i<1||i>Ptrl->last+1)
{
cout << "输入的位置不合法"<<endl;
return;
}
for(int j=i;j<=Ptrl->last;j++)
{
Ptrl->arr[j-1] = Ptrl->arr[j];
}
Ptrl->last--;
Ptrl->arr[(Ptrl->last)+1] = 0;
return;
}
//查找
int Find(int x,List Ptrl)
{
int i=0;
while(x!=Ptrl->arr[i]&&i<=Ptrl->last)
i++;
if(i<=Ptrl->last) return i;
else return -1;
}
建立一个线性表并输出元素,在第二个位置插入23,此时共11个元素,打印结果正确,再删除第二个元素,那么23应该被删除,此时第2个元素又是200了,第9个元素应该是原来的1000,第十位没有元素。
代码结果:
顺序存储在中间插入删除元素太麻烦,因为要移动很多元素
二、线性表的链式存储
无头指针!!!!
#include<iostream>
using namespace std;
typedef struct Node* List;
struct Node
{
int data;
List Next;
};
List Ptrl;
//初始化
List MakeList(List& Ptrl)
{
int data;
Ptrl = new struct Node;
cin >> data;
Ptrl->data = data;
List Tail=Ptrl;
for(int i=2;i<=10;i++)
{
cin >> data;
List p = new struct Node;
p->data = data;
Tail->Next = p;
p->Next=NULL;
Tail = Tail->Next;
}
return Ptrl;
}
int Length(List Ptrl)
{
int i=0;
List p=Ptrl;
while(p)
{
i++;
p=p->Next ;
}
return i;
}
//按值寻找元素
List Find(int x,List Ptrl)
{
while(x!=Ptrl->data&&Ptrl!=NULL)
Ptrl = Ptrl->Next;
if(Ptrl!=NULL) return Ptrl;
}
//按序号寻找元素
List Findth(int j,List Ptrl)
{
List p=Ptrl;
if(j>Length(p))
{
cout << "输入序号大于列表长度"<<endl;
}
else
{
for(int i=1;i<j;i++)
{
p = p->Next;
}
return p;
}
}
//插入
//S—>Next=P—Next;
//P—>Next=S;
//不能互换;否则地址成环路了
List Insert(int x,int i,List Ptrl) //第一个if用于表头,因为表头比较特殊,前面没有相邻元素。 //第二个if用于检测是否插入线性表中,即前面有相邻元素才可以。
{
if(i==1)
{
List s = new struct Node;
s->Next = Ptrl;
s->data = x;
return s;//返回新表头指针
}
List p=Findth(i-1,Ptrl);
if(p==NULL)
{
cout << "输入位置在链表之外"<<endl;
return NULL;
}else
{
List s = new struct Node;
s->Next = p->Next;
s->data = x;
p->Next = s;
return Ptrl;//返回表头指针
}
}
//删除
List Delete(int i,List Ptrl)
{
List temp;
if(i==1)
{
List p = Ptrl;
if(p!=NULL)
{
p = p->Next;
return p;
}
else return NULL;
free(p);
}
List s = Findth(i-1,Ptrl);
if(s==NULL)
{
cout << "该结点压根不存在"<<endl;
}else if(s->Next==NULL)
{
cout << "该结点不存在,但它的前一个结点存在"<<endl;
}else
{
temp = s->Next;
s->Next = temp->Next;
free(temp);
return Ptrl;
}
}
int main()
{
Ptrl = MakeList(Ptrl);
//cout << Head->data<<endl;
cout << Length(Ptrl)<<endl;//打印表长,应该为10
cout << Findth(2,Ptrl)<<endl;//按序号查找元素地址
Insert(100,3,Ptrl);
cout << Ptrl->Next->data <<endl;
cout << Ptrl<<endl;//这里是为了验证删除前后Ptrl仍然没变,仍然指向该链表头结点
cout << Findth(2,Ptrl)<<endl;//返回2号元素的地址
cout << Delete(2,Ptrl)<<endl;//返回删除后的链表
}
结果:
链式存储方便在中间插入或删除元素,但是不方便在链尾删除元素,因为链尾删除元素时需要将尾指针设为NULL,但是不方便找尾结点地址。