0.PTA得分截图
1.本周学习总结
1.1 总结线性表内容
- 顺序表
1.顺序表结构体定义
#define MaxSize 50 //设置线性表最大长度,方便修改
typedef int ElemType; //为int类型取别名ElemType
typedef struct
{
ElemType data[MaxSize]; //定义数组存放线性表元素
int length; //记录线性表长度
}SqList,*List; //定义顺序表类型
2.顺序表的建立
void CreatList(List &L,ElemType a[],int n) //由传入的a中的n个元素来建立线性表
{
int i=0;
int k=0; //k表示L中元素个数,开始顺序表为空,所以K初始值为0
L=new SqList; //给顺序表分配空间
while(i<n) //利用while循环扫描数组a
{
L->data[k]=a[i]; //将数组a中的元素a[i]放入L中
k++;
i++;
}
L->length=k; //记录顺序表长度为k
}
3.顺序表的元素插入(利用布尔类型来返回插入结果,返回True表示插入成功,返回False表示插入失败)
bool ListInsert(List &L,int i,ELemType e)
{
int j;
if(i<1||i>L->lengeh+1) //若参数i小于1或者大于数组长度+1,则改参数错误,返回False
{
return False;
}
i--; //将插入位置的逻辑序号转换成为对应的物理序号
for(j=L->length;j>i;j--) //若该位置存在,则将该位置及其后的所有元素后移一位
{
L->data[j]=L->data[j-1];
}
L->data[i]=e; //将待插入元素e插入
L->length++; //因为插入一个元素,所以顺序表元素多了一个,顺序表长度增1
return True; //插入成功,返回True
4.顺序表元素的删除(利用布尔类型来返回删除结果)
bool ListDelete(List &L, int i, ElemType &e)
{
int j;
if(i<1||i>L->lengeh+1) //若参数i小于1或者大于数组长度+1,则改参数错误,返回False
{
return False;
}
i--;
e=L->data[i];
for(j=i;j<L->length;j++) //利用循环覆盖第i个值
{
L->data[j]=L->data[j+1];
}
L->length--; //因为成功删除第i个值,元素少了一个,顺序表长度减1
return True; //删除成功,返回True
}
- 链表
1.链表结构体定义
typedef int ElemType;
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LinkNode,*LinkList;
2.头插法,尾插法建链表
//头插法建链表
void CreateListF(LinkList& L, int n)
{
L = new LNode;
L->next = NULL;
LinkList p;
while (n--)
{
p = new LNode;
cin >> p->data;
p->next = L->next;
L->next = p;
}
}
//尾插法建链表
void CreateListR(LinkList& L, int n)
{
L = new LNode;
LinkList p;
LinkList ptail = L;
ptail->next = NULL;
while (n--)
{
p = new LNode;
cin >> p->data;
ptail->next = p;
ptail = p;
}
ptail->next = NULL;
}
3.链表插入
void ListInsert(Linklist& L, int i, ElemType e)
{
LinkList p;
p = L->next;
j = 0;
while (p && j < i - 1)
{
p = p->next;
j++;
}
if (!p || i <= 0)
{
cout << "位置错误!" << endl;
}
else
{
s = new node();
s->data = e;
s->next = p->next;
p->next = s;
}
}
4.链表删除
void ListDelete(Linklist& L, int i)
{
LinkList p;
p = L->next;
j = 0;
while (p->next && j < i - 1)
{
p = p->next;
j++;
}
if (!p || i <= 0)
{
cout << "位置错误!" << endl;
}
else
{
s = new node();
s = p->next;
p->next = p->next->next;
delete s;
}
}
5.链表分割
void SplitList(LinkList& L, LinkList& L1, LinkList& L2)
{
LinkList p;
LinkList prev;
LinkList ptail;
L2 = new LNode;
prev = L->next;
L1 = L;
L1->next = NULL;
L2->next = NULL;
ptail = L1;
int i;
for (i = 1; prev; i++, prev = prev->next)
{
p = new LNode;
p->data = prev->data;
p->next = NULL;
if (i % 2 == 1)
{
ptail->next = p;
ptail = p;
}
else
{
p->next = L2->next;
L2->next = p;
}
}
}
- 有序表(有序单链表)
1.插入
void ListInsert(LinkList& L, ElemType e)
{
LinkList x = L;
LinkList p = new LNode; //新开辟p一个节点存储传入的值e
p->data = e;
while (x->next && x->next->data < e) //利用while循环来寻找插入位置
{
x = x->next;
}
p->next = x->next; //将存储e的新节点插入找到的位置中
x->next = p;
}
2.删除
void ListDelete(LinkList& L, ElemType e)
{
int flag = 1; //利用flag来判断成功删除传入数据e,给flag赋初值1
LinkList x = new LNode;
LinkList p = L;
x->next = NULL;
if (p->next == NULL)
{
return;
}
while (p->next) //利用while循环来寻找待删除元素,一旦找到该待删除元素,终止循环,并将flag的值变为e
{
if (p->next->data == e)
{
x = p->next;
p->next = x->next;
flag = 0;
delete x; //找到该元素之后链表中删除该元素,并释放该节点
break;
}
p = p->next;
}
if (flag == 1) //若未找到该元素,则输出"找不到!"
{
cout << e << "找不到!" << endl;
}
}
3.有序表合并
void MergeList(LinkList &L1,LinkList L2)
{
LinkList p, head;
head = L1;
while (L2->next&&head->next)
{
if (head->next->data > L2->next->data)
{
p = new LNode;
p->data = L2->next->data;
p->next = head->next;
head->next = p;
L2 = L2->next;
}
else if(head->next->data == L2->next->data)
{
L2 = L2->next;
}
head = head->next;
}
if (head->next == NULL)
{
head->next = L2->next;
}
}
- 双向链表操作
0.主函数
int main()
{
LinkList L;
LinkList Lr; //存储链表尾结点,方便反向对链表进行操作
int n;
cin >> n;
CreateList(L, n, Lr);
DispListF(L);
DispListR(L, Lr);
DestroyList(L);
return 0;
}
1.双向链表的结构体定义
typedef int ElemType;
typedef struct node
{
ElemType data;
struct node* pre; //指向前一节点的指针
struct node* next; //指向后一节点的指针
}LNode, *LinkList;
2.双向链表建立
void CreateListR(LinkList& L, int n, LinkList& Lr)
{
L = new LNode;
L->next = NULL;
L->pre = NULL;
LinkList p, ptail;
ptail = L;
while (n--)
{
p = new LNode;
cin >> p->data;
p->next = ptail->next;
ptail->next = p;
p->pre = ptail;
ptail = p;
}
Lr = ptail;
}
//正向输出链表
void DispListF(LinkList L)
{
LinkList p;
p = L->next;
if (p != NULL)
{
while (p->next)
{
cout << p->data << " ";
p = p->next;
}
cout << p->data << endl;
}
else
{
cout << "空链表!" << endl;
}
}
//利用主函数中存储的尾结点位置,直接反向输出链表
void DispListR(LinkList L, LinkList Lr)
{
LinkList p;
p = Lr;
while (p->pre->pre)
{
cout << p->data << " ";
p = p->pre;
}
cout << p->data << endl;
}
结构特点:有两个指针,一个指向后继节点,一个指向前驱结点
- 单循环链表
1.结构体定义
typedef int ElemType;
typedef struct node
{
ELemType data;
struct node* next;
}CLNode, *CLLinkList;
2.单循环链表的建立
void CreateListR(CLLinkList& L, int n)
{
L = new LNode;
LinkList p;
LinkList ptail = L;
ptail->next = NULL;
while (n--)
{
p = new LNode;
cin >> p->data;
ptail->next = p;
ptail = p;
}
ptail->next = L;
}
结构特点:链表呈环状,可以从链表的任意位置对整个链表进行遍历
1.2 学习体会
使用链表存储数据较为简便,方便对存储数据进行插入、删除等改动。
在学习过程中,主要遇到的问题有两点:
1.开始的时候对链表的操作不熟练,导致循环时判断条件的使用错误,导致循环结束的位置不正确。
2.在使用循环的时候因为没有转换思维,喜欢使用两层循环,导致提交时产生运行超时的问题。
2.PTA实验作业
2.1 有序链表合并
- 2.1.1 代码截图
- 2.1.2 本题PTA提交列表说明
Q1:第一次在合并链表的时候,遇到相同元素我并未删除,而是将两个元素一起放入链表。
A1:发现这个问题之后,在两个数据相同是,我删除了第二个表的数据,将第一个表的数据放入新合并的表中
2.2 有序链表合并
- 2.1.1 代码截图
- 2.1.2 本题PTA提交列表说明
Q1:第一次因为分割时操作不当导致原有链断裂,导致代码运行出错
A1:新开辟结点存储数据,加入第二条链,是原有链不断裂
Q2:未注意题中的要求第二条链为倒序
A2:对第二条链使用头插法
2.2 有序链表合并
2.1.1 代码截图
2.1.2 本题PTA提交列表说明
Q1:第一次使用链表存储,导致存储时代码出问题,无法编译
A1:后使用数组存储,内容存储系数,下表为指数