1、长度为n的线性表A采用顺序存储结构。请写一算法,找出该线性表中值最小的数据元素,给出该元素在表中的位置。
ElemType FINDMIN(ElemType A[], int n)
{
ElemType min = A[0];
for(i=1; i < n; i++)
if(A[i] < min)
min = A[i];
return min;
}
2.设计一个算法.用不多于3n/2的平均比较次数,在顺序表A[1.. n]中分别找出最大值元素和最小值元素。
最坏从大到小,每个都比较两次:2(n-1)。
最好从小到大,每个只比较一次:n-1。
平局[2(n-1) + n-1] / 2 = 3n/2 - 3/2;
void MAXMIN(int A[], int n)
{
int i, max=A[0], min = A[0];
for(i = 1; i < n; i++)
if(A[i] > max)
max = A[i];
else if(A[i] < min)
min = A[i];
printf("manx = %d, min = %d\n", max, min);
}
3.已知长度为n的线性表A采用顺序存储结构,并假设表中每个数据元素均为整型数据,请写出在该顺序表中查找值为item的数据元索的递归算法。若查找成功,算法返回item在表中的位置,否则,算法返回信息-1。
int SEQSEARCH(int A[], int n, int item, int pos)
{
if(pos > n)
return -1;
if(A[pos] == item)
return pos;
return SEQSEARCH(A, n, item, pos+1);
}
4.已知长度为n的线性表A采用顺序存储结构。请写出逆转该线性表的算法,即由A=(a1,a2...an-1,an)产生A'(=(an,a-1...,a2 ,a1),要求在逆转过程中用最少的附加空间(用尽可能少的辅助变量)。
void REVERSE(ElemType A[], int n)
{
ElemType temp;
int i;
for(i = 0; i < n/2; i++)
{
temp = A[i];
A[i] = A[n-i-1];
A[n-i-1] = temp;
}
}
5. 已知长度为n的线性表A采用顺序存储结构, 并且每个数据元素均为一个无符号整数,请写一算法,删除线性表中的所有奇数。
void DELETEODD(int A[], int &n)
{
int i = 0;
while(i < n)
{
if(A[i]%2 != 0)
DELETELIST(A, n, i+1);
else
i++;
}
}
6.已知长度为n的线性表A采用顺序存储结构。请写一时间复杂度为O(n)的算法,该算法删除线性表中原来序号为奇数的那些数据元素。
void DELODD(ElemType A[], int &n)
{
int i = 1; j = -1;
while(i <= n)
{
A[++j] = A[i];
i+= 2;
}
n = j+1;
}
7.已知长度为n且按值有序排列的线性表A采用顺序存储结构。请写一算法,删除所有值大于x且小于y的数据元素。
void DELXY(ElemType A[], int &n, ElemType x, ElemType y)
{
int k, pos, i = 0, j = n-1;
while(A[i] < x) i++;
while(A[j] > y) j--;
pos = i;
for(k = j+1; k < n; k++)
A[i++] = A[k];
n = n-j+pos-1;
}
8.请写一算法,通过键盘输人一系列数据元素,建立一个长度为n且不包含重复元素的线性表A。这里,设线性表A采用的存储结构为顺序存储结构,并且假设空间足够。
void BUILDLIST(int A[], int n)
{
int flag = 0, i = 0, j;
scanf("%d", &A[0]);
while(i < n-1)
{
scanf("%d", &A[i+1]);
for(j = 0; j < i; j++)
{
if(A[j] == A[i+1])
{
flag = i;
break;
}
}
if(flag == 0)
i++;
else
flag = 0;
}
}
9.已知线性表A与线性表B的长度分别为n与m,并且都采用顺序存储结构。请写一算法,在线性表A的第i个位置插人线性表B。约定:不考虑存储空间溢出问题。
int INSERTAB(ElemType A[], int n, ElemType B[], int m, int i)
{
int j;
for(j = n-1; j > i-2; j--)
A[j+m] = A[j];
for(j = 0; j < m; j++)
A[i+j-1] = B[j];
return m+n;
}
10.已知线性链表第1个结点的存储地址为list。请写一算法,把该链表中数据域值为d的所有结点的数据域值修改为item。
void MODIFY(LinkList list, ElemType d, ElemType item)
{
LinkList p = list;
while(p != NULL)
{
if(p->data == d)
p->data = item;
p = p->link;
}
}
11.已知非空线性链表的第1个结点的指针为list,请写出删除该链表第i个结点的算法。
int DEL1(LinkList &list, int i)
{
LinkList r, q = list;
int k;
if(i == 1)
list = list->next;
else
{
for(k = 1; k < i; k++)
{
r = q;
q = q->link;
if(q == NULL)
return -1;
}
r->link = q->link;
}
free(q);
return 1;
}
12.已知非空线性链表第1个结点的存储地址为list,请写出删除链表中从第i个结点开始的(包括第i个结点本身)连续k个结点的算法。
LinkList DEL2(LinkList list, int i, int k)
{
LinkList p, q = list;
int j;
if(i==1)
for(j = 1; j <= k; j++)
{
q = list;
list = list->link;
free(q);
}
else
{
for(j = 1; j < i-1; j++)
q = q->link;
for(j = 1; j <=k; j++)
p = q->link;
q->link = p->link;
free(p);
}
return list;
}
13.已知线性链表第1个结点指针为list。请写一算法,删除链表中数据域值最大的结点。
LinkList DELMAX(LinkList list)
{
LinkList p, q, r, s;
q = list;
p = list->link;
r = list;
while(p != NULL)
{
if(p->data > q->data)
{
q = p;
s = r;
}
r = p;
p = p->link;
}
if(q == list)
list = list->link;
else
s->link = q->link;
free(q);
return list;
}
14.已知线性链表第1个结点指针为list.请写一算法.判断该链表是否是有序链表(结点是否按照数据域值的大小链接),若是,算法返回1,否则,算法返回0。
int ISSORT(LinkList list)
{
LinkList r = list, p = list->link;
while(p != NULL)
{
if(p->data < r->data)
return 0;
r = p;
p = p->link;
}
return 1;
}
15. 已知线性链表第1个链结点指针为list。 请写一算法,交换p所指结点与其下一个结点的位置(假设p指向的不是链表中最后那个结点)。
LinkList EXCHANGE(LinkList list, LinkList p)
{
LinkList q = list;
if(p == list)
{
list = list->link;
p->link = p->link->link;
list->link = p;
}
else
{
while(q->link != p)
q = q->link;
q->link = p->link;
p->link = p->link-link;
q->link->link = p;
}
return list;
}
16.已知非空线性链表第1个结点由list 指出。请写一算法 ,将链表中数据域值最小的链结点移到链表最前面。
LinkList REMOVE(LinkList list)
{
LinkList p, q, r, s;
q = list;
p = list->link;
r = list;
while(p != NULL)
{
if(p->data < q->data)
{
s = r;
q = p;
}
r = p;
p = p->link;
}
if(q != list)
{
s->link = q->link;
q->link = list;
list = q;
}
return list;
}
17. 请写-算法,该算法用尽可能高的时间效率找到由list 所指的线性链表的倒数第k个结点。若找到这样的结点,算法给出该结点的地址;否则,算法给出信息NULL.限制,算法中不得求出链表的长度也不允许使用除指针变量和控制变量以外的其他辅助空间。
LinkList SEARCHNODE(LinkList list, int k)
{
LinkList p, r;
int i;
if(list != NULL && k > 0)
{
p = list;
for(i = 1; i < k; i++)
{
p = p->link;
if(p == NULL)
{
printf("no NO.k node\n");
return NULL;
}
}
r = list;
while(p->link != NULL)
{
p = p->link;
r = r->link;
}
}
return r;
}
18.设线性表X=(x1,x2..xn)与Y=(y1,y2...ym)都采用链式存储结构(链表第1个结点的指针不妨分别用x和Y表示)。试写一个算法合并这两个线性链表为一个线性链表,使得
Z= (x1 ,y1,X2,y2..,Xm ,Ym ,Xm+1,..,Xn m≤n
(x1 ,Y1,X2, Y2,.,Xn,Yn, Yn+1'..Ym m>n
LinkList COMBINE(LinkList X, LinkList Y)
{
LinkList p, q, Z = X;
if(X->link == NULL)
X->link = Y;
else
{
do
{
p = X->link;
q = Y->link;
X->link = Y;
Y->link = p;
X = p;
Y = q;
}while(p->link != NULL && q!= NULL);
if(p->link == NULL)
X->link = Y;
}
return Z;
}
19. 已知线性链表第1个结点的指针为list. 请写-算法、删除数据域值相同的多余结点,即若链表中有多个结点具有相同的数据域值,只保留其中一个结点,其余结点均从链表的最后删
从第二个节点开始判断之前是否出现过,出现过删除,否则后移。
void DEL3(LinkList list)
{
LinkList p, q, r, flag = 0;
p = list->link;
r = list;
while(p != NULL)
{
q = list;
while(q != p)
{
if(q->data == p->data)
{
r->link = p->link;
free(p);
flag = 1;
break;
}
else
q = q->link;
}
if(flag)
{
p = r->link;
flag = 0;
}
else
{
r = p;
p = p->link;
}
}
}
去,使得到的链表中所有结点的数据域值都不相同。
20.诸写一算法,依次输出通过键盘输人的一组整型数据中的最后k个元素。约定:以Cr1+z作为键盘输人的结束,并假设k≤输人的数据元素的个数。限制:算法中不允许使用数组,也不允许有计算输入数据个数的过程。
建立长度为k的循环链表,最后输出既是
void PRINTELE(int k)
{
LinkList list, p, r;
int i, a;
list = (LinkList)malloc(sizeof(LNode));
list->data = 0;
r = list;
for(i = 1; i < k; i++)
{
p = (LinkList)malloc(sizeof(LNode));
p->data = 0;
r->link = p;
r = p;
}
r->link = list;
p = list;
while(scanf("%d",&a") > 0)
{
p->data = a;
p = p->link;
}
for(i = 1; i <= k; i++)
{
if(p->data != 0)
printf("%d", p->data);
p = p->link;
}
}
21.已知一个不带头结点也无头指针变量,并且长度大于1的循环链表。请写一算法,删除p所指链结点的直接前驱结点。
void DEL4(LinkList p)
{
LinkList r, q;
r = p;
q = p->link;
while(q->link != p)
{
r = q;
q = q->link;
}
r->link = p;
free(q);
}
22.请写出将一个线性链表(第1个结点的存储地址为list)分解为两个循环链表,并将两个循环链表的长度存放在各自的头结点的数据域中的算法。你以分解规则:若线性链表中某一链结点属于第 1个循环链表,则下一个链结点就属于第2个循环链表;反之,若线性链表中某一一个链结点属于第2 个循环链表,则下一个链结 点就属于第1个循环链表。
LinkList list1, list2;
void SEPARATE(LinkList list)
{
LinkList r1, r2, p = list;
int flag = 1;
list1 = (LinkList)malloc(sizeof(LNode));
list1->data = 0;
r1 = list1;
list2 = (LinkList)malloc(sizeof(LNode));
list2->data = 0;
r2 = list2;
while(p != NULL)
{
if(flag == 1)
{
r1->link = p;
r1 = p;
list1->data++;
flag = 2;
}
else
{
r2->link = p;
r2 = p;
list2->data++;
flag = 1;
}
p = p->link;
}
r1->link = list1;
r2->link = list2;
}
23.已知带头结点的循环链表的头结点指针为list,请编写一个逆转链表链接方向的算法。
void INVERTCIR(LinkList list)
{
LinkList p, q, r;
p = list->link;
q = list;
while(p != list)
{
r = q;
q = p;
p = p->link;
q->link = r;
}
list->link = q;
}
24.已知非空线性表(a1,a2,,.,.., a-1, an )采用仅设置了末尾结点指针的单向循环链表作为存储结构(设末尾结点指针为rear),请写一算法,将线性表改造为(a,a2, .,an-1,an,an-1..,a2,a1)。要求:改造后的线性表依然采用仅设置末尾结点指针的单向循环链表存储,并且算法中只能出现一个循环。
LinkList CIRMODIFY(LinkList rea)
{
LinkList p, q, r, s;
q = rear->link;
p = (LinkList)malloc(sizeof(LNode));
p->data = q->data;
r = p;
p->link = rear->link;
rear->link = p;
q = q->link;
while(q != rear)
{
s = q->link;
p = (LinkList)malloc(sizeof(LNode));
p->data = q->data;
p->link = rear->link;
rear->link = p;
q = s;
}
rear = r;
return rear;
}
25.已知某一元n阶多项式f(x)= 求和(i=1~n) ai*(x^ei)采用(a1,e1),(a2,e2),.,(an,en)作为输人,请写一算法,生成f(x)按降幂排列的线性链表结构(ei之间按值大小无序 )。
typedef struct node
{
int coef, exp;
struct node *link;
}LNode, *LinkPoly;
LinkPoly POLY(int n)
{
LinkPoly p, q, r, list = NULL;
int k;
for(k = 1; k <= n; k++)
{
p = (LinkPoly)malloc(sizeof(LNode));
scanf("%d%d",&(p->coef),&(p->exp));
p->link = NULL;
if(list == NULL)
list = p;
else
{
q = list;
while(q != NULL)
{
if(p->exp > q->exp)
{
p->link = q;
if(q == list)
list = p;
else
r->link = p;
break;
}
else
{
r = q;
q = q->link;
}
}
if(q == NULL)
r->link = p;
}
}
return list;
}
26.已知不带头结点的双向链表第1个结点的指针为list, 链结点中除了数据域和分别指向该结点直接前驱结点和直接后继结点的指针域外,还设置了记录该结点被访问的次数的频度域freq(初始值为0)。请设计一个算法LOCATE(list,x),该算法的功能是每当在此链表上进行一次LOCATE(list,x)操作,数据信息为x的结点的freq域的值增1,并且保持链表中链结点按freq域值递减链接,以使得频繁被访问的链结点靠近链表的前端。
每次查找x节点,将freq增加1,在和直接前驱比较,若大于前驱节点,则交换位置
int LOCATE(DLinkList list, ElemType x)
{
DLinkList p = list->rlink, q;
while(p != NULL && p->data != x)
p = p->rlink;
if(p == NULL)
return 0;
else
{
p->freq++;
q = p->link;
while(q != list && q->freq < p->freq)
{
p->llink = q->llink;
p->llink->rlink = p;
q->rlink = p->rlink;
if(q->rlink != NULL)
q->rlink->llink = q;
p->rlink = q;
q->llink = p;
q = p->llink;
}
}
return 1;
}
27.已知带有头结点的双向循环链表中头结点的指针为list,请写出删除并释放数据域内容为x的所有结点的算法。
void DELETEX(DLinkList list, ElemType x)
{
DLinkList p = list->rlink;
while(p != list)
{
if(p->data == x)
{
p->llink->rlink = p->rlink;
p->rlink->llink = p->llink;
free(p);
}
p = p->rlink;
}
}
28.已知不带头结点的双向循环链表第1个结点指针为list,请写一算法 ,判断该链表是否为对称链表,即前后对应结点的数据信息相同。对称返回1,否则返回0。
int SYMMETRY(DLinkList list)
{
DLinkList front = list, rear = list->link;
int flag = 0;
while(flag == 0 && frong->data == rear->data)
{
front = front->rlink;
rear = rear->llink;
if(front == rear || front->link == rear)
flag = 1;
}
if(flag = 1)
return 1; //对称
else
return 0; //非对称
}
29.请写一算法,该算法的功能是先通过键盘输人n个整型数据,建立一个 带有头结点的双向循环链表,然后按照与输人相反的次序依次输出这n个整型数据。
头插法
DLinkList INOUT(DLinkList list, int n)
{
DLinkList p;
int i;
list = (DLinkList)malloc(sizeof(DNode));
list->llink = list;
list->rlink = list;
for(i = 1; i < n; i++)
{
p = (DLinkList)malloc(sizeof(DNode));
scanf("%d",&(p->data));
p->llink = list;
p->rlink = list->rlink;
list->rlink->llink = p;
list->rlink = p;
}
p = list->link;
while(p != list)
{
printf("%5d",p->data);
p = p->rlink;
}
return list;
}
30.已知带头结点的双向循环链表头结点指针为list,除头结点外的每个链结点数据域值为一个整数。请写-算法,将链表中所有数据域值大于0的结点放在所有数据域值小于0的结点之前。若链表中除头结点外没有其他结点,算法返回0,否则,算法返回1.
p,q两指针,左右移动找对应数据
int DMOVE(DLinkList list)
{
DLinkList p = list->rlink, q = list->llink;
int temp;
if(p == list)
return 0;
while(p != q)
{
while(p->data > 0 && p != list)
p = p->rlink;
while(q->data < 0 %% q != list)
q - q->llink;
if(q->rlink != p)
{
temp = p->data;
p->data = q->data;
q->data = temp;
p = p->rlink;
q = q->llink;
if(q->rlink == p || (p == list && q == list))
return 1;
}
else
return 1;
}
}