//
最近开设了数据结构的课程,我会整理成一个系列,帮助自己整理和巩固知识点。
题目
请完成下列算法填空现对单链表的逆置存储,逆置存储是指将元素线性关系逆置后的链表存储,例如(a0,a1,a2),关系逆置后为(a2,a1,a0).
单链表结点Node和单链表SingleList结构体定义如下:
typedef struct node
{
ElemType element;
struct node *link;
}Node;
typedef struct singlelist
{
Node *first;
int n;
}SingleList;
void invert(SingleList *L) {
Node *p=__________,*q;
L->first=NULL;
while (_____) {
q=p->link;
p->link=_______;
L->first=_______;
p=_______; }
}
解答
void invert(SingleList *L) {
Node *p=__L->first__,*q;
L->first=NULL;
while (_p!=NULL_) {
q=p->link;
p->link=_L->first_;
L->first=__p__;
p=__q__; }
}
这里的思路是源于L->first=NULL; 题目要把链表首地址置为空,是要重新排列链表。
第一次循环,将q指向第二个结点,把第一个结点取下,然后拼到链表头结点上,然后p指针向后移;
第二次循环,将q指向第三个结点,把第二个结点取下,然后拼到头结点后、第一个结点前,然后p指针后移。以此类推,直到p移到了原链表的尾部结束循环。
题目
完成下列算法填空,将两个有序递增的带表头结点的单链表合并为一个有序递增的单链表。
链表结点Node和链表SingleList结构体定义如下:
typedef struct node
{
ElemType element;
struct node *link;
}Node;
typedef struct headerlist
{
Node *head;
int n;
}HeaderList;
void MergeList1(HeaderList *La,HeaderList *Lb,HeaderList *Lc) {
//合并链表La和Lb,合并后的新表使用头指针Lc指向
Node *pa,*pb,*pc,*q;
pa=La->head->link;
pb=Lb->head->link;
pc=Lc->head;
while(pa && pb) {
if(____________________) {
pc->link=pa;
pc=pa;
pa=pa->link;
La->n--;
}
else if(pa->element>pb->element) {
pc->link=___________;
pc=________;
pb=_________;
Lb->n--;
}
else {
pc->link=pa;
pc=pa;
pa=_________;
q=_________;
free(pb);
pb =q;
}
Lc->n++;
}
pc->link=pa?pa:pb; //插入剩余段 Lc->n+=pa?La->n:Lb->n;
}
解答
while(pa && pb) {
if(pa->element<pb->element) {
pc->link=pa;
pc=pa;
pa=pa->link;
La->n--; }
else if(pa->element>pb->element) {
pc->link=___pb___;
pc=__pb__;
pb=__pb->link___;
Lb->n--; }
else {
pc->link=pa;
pc=pa;
pa=__pa->link__;
q=__pb->link__;
free(pb);
pb =q; }
Lc->n++; }
pc->link=pa?pa:pb;
}
这题可以根据上下步骤解答。画图后思路清晰简单~
题目
请完成算法填空,实现带表头结点的单链表形式实现的队列上的元素入队与出队操作,队列和元素结点结构体定义如下:
typedef struct node
{
ElemType element;
struct node* link;
}Node;
typedef struct queue
{
Node* front; //注意front指向表头结点,非头结点
Node* rear; //指向尾结点
}Queue;
void EnQueue(Queue *Q, ElemType x)
{
Node* p= (Node*)malloc(sizeof(Node));
____________ = x;
p->link = NULL;
____________=p;
Q->rear=p;
}
void DeQueue(Queue *Q)
{
//若队列为空,直接返回
if(___________ ==NULL)
return;
Node *p=_____________;
Q->front->link=___________;
free(p);
//若出队后,队列为空,则需重置rear
if(______________==NULL)
Q->rear=Q->front;//指向表头结点
}
解答
void EnQueue(Queue *Q, ElemType x)
{
Node* p= (Node*)malloc(sizeof(Node));
__p->element__ = x;
p->link = NULL;
__rear->link___=p;
Q->rear=p;
}
void DeQueue(Queue *Q)
{
if(___Q->front____ ==NULL)
return;
Node *p=___Q->front->link___;
Q->front->link=__p->link__;
free(p);
if(____Q->front_____==NULL)
Q->rear=Q->front;
}
这题是对链队列的入队和出队操作,分别从对尾和队头进行增加结点和删除结点的操作。
首先,这里的删除队头结点是逻辑删除,只是不再被指向。其次,删除头结点是front指向的第一个结点的下一个结点。
题目
带表头结点的一元多项式结构定义如下:
typedef struct pNode
{
int coef;
int exp;
struct pNode *link;
}pNode;
typedef struct
{
struct pNode *head;
}polynominal;
编写程序,实现一元多项式的创建、输出、销毁、相加、相乘操作。
解答
- 创建
int Create(polynominal *L)
{
int power; //最高次幂
int i;
int tempCoef;
pNode* p = NULL;
pNode* q = (pNode*)malloc(sizeof(pNode)); //生成新结点
L->head = (pNode *)malloc(sizeof(pNode));
if (!L->head)
{
return ERROR;
}
//初始化头结点
L->head->link = NULL;
p = L->head;
printf("请输入一元多项式的最高次幂的次数。\n");
scanf("%d", &power);
L->head->exp = power;
for (i=power; i>=0; i--)
{
printf("请输入%d次方的系数",i);
scanf("%d", &tempCoef);
q->coef = tempCoef;
q->exp = i;
q->link = NULL;
p->link = q;
p = q;
q = (pNode*)malloc(sizeof(pNode)); //重置q
}
return OK;
}
- 输出
int Output(polynominal L)
{
pNode* p;
if (!L.head)
{
return ERROR; //空链表
}
p = L.head->link;
while (p)
{
if (p->exp == 0)
{
printf("%d", p->coef);
break;
}
if (p->coef != 0)
{
printf("%dX^%d+", p->coef, p->exp);
}
p = p->link;
}
return OK;
}
- 销毁
void Destory(polynominal *L)
{
pNode* p;
while (L->head)
{
p = L->head->link;
free(L->head);
L->head = p;
}
}
- 相加
int Add(polynominal L1, polynominal L2, polynominal *L)
{
int j;
pNode* p = L1.head->link;
pNode* q = L2.head->link;
int n1 = L1.head->exp;
int n2 = L2.head->exp;
if ((n1 - n2)>0) //L1比L2长
{
for (j = n1 - n2; j > 0; j--)
{
p = p->link;
}
while (q&&p)
{
p->coef += q->coef;
q = q->link;
p = p->link;
}
L->head = L1.head;
}
else if((n1 - n2) < 0) //L1比L2短
{
for (j = n2 - n1; j > 0; j--)
{
q = q->link;
}
while (q && p)
{
q->coef += p->coef;
p = p->link;
q = q->link;
}
L->head = L2.head;
}
else //L1和L2一样长
{
while (q && p)
{
p->coef += q->coef;
q = q->link;
p = p->link;
}
L = &L1;
}
return OK;
}
- 相乘
void Multiply(polynominal L1, polynominal L2, polynominal* L)
{
int power;
power = L1.head->exp + L2.head->exp;
pNode* p = NULL;
L->head = (pNode*)malloc(sizeof(pNode));
//初始化头结点
L->head->link = NULL;
L->head->exp = power;
p = L->head;
for (int i = 0; i <= power; i++) {
pNode* q;
q = (pNode*)malloc(sizeof(pNode));
q->coef = 0;
q->exp = power - i;
q->link = NULL;
p->link = q;
p = p->link;
}
p = L->head->link;
pNode* a = L1.head->link;
pNode* b = L2.head->link;
while (a) {
b = L2.head->link;
while (b) {
int temp = a->exp + b->exp;
while (p->exp != temp) {
p = p->link;
}
p->coef += a->coef * b->coef;
p = L->head->link;
b = b->link;
}
a = a->link;
}
}
在这题中,我在头结点插入了当前一元多项式的最高次幂,方便后续操作。
所有都以最高次幂为前提进行操作。
比如:
- 创建链表时要提前规定好最高次幂的数值,该数值就等于结点数。然后依次输入不同次数对应的系数,如果某个系数不存在,他的系数就为0。
- 两个链表相加时,提前获取两个链表的最高次幂的数值,然后判断新链表的结点个数。
- 两个链表相乘时,也是提前获取两个链表的最高次幂的数值,然后创建两个最高次幂相加个数量的结点作为新链表。