线性表代码
顺序表综合应用
1.从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删元素的值。空出的位置由最后一个元素填补,若顺序表为空,则显示出错信息并退出运行
//题目01
bool Del_Min(SqList& L, ElemType& value) {
//删除顺序表L中最小值元素结点,并通过引用型参数value返回其值
//若删除成功,则返回true,否则返回false
if (L.length == 0)
return false; //表空,中止操作返回
value = L.data[0];
int pos = 0; //假定0号元素的值最小
for(int i=1;i<L.length;i++) //遍历寻找最有最小值的元素
if (L.data[i] < value){ //让value记忆当前具有最小值的元素
value = L.data[i];
pos = i;
}
L.data[pos] = L.data[L.length - 1]; //空出的位置由最后一个元素填补
L.length--;
return true; //此时,value即为最小值
2.设计一个高效算法,将顺序表 L L L的所有元素逆置,要求算法的空间复杂度为 O ( 1 ) O(1) O(1)
//题目02
void Reverse(SqList& L) {
ElemType temp;
for (int i = 0; i < L.length / 2; i++){
temp = L.data[i]; //交换L.data[i]与L.data[L.length-i-1]
L.data[i] = L.data[L.length - i - 1];
L.data[L.length - i - 1] = temp;
}
}
3.对长度为 n n n的顺序表 L L L,编写一个时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( 1 ) O(1) O(1)的算法,该算法删除线性表中所有值为 x x x的数据元素
//题目03
//解法一:用k记录顺序表L中不等于x的元素个数(即需要保存的元素个数),
//扫描时将不等于x的元素移动到下表k的位置,并更新k值。扫描结束后修改L的长度。
void del_x_1(SqList& L, ElemType x) {
int k = 0, i; //k记录值不等于x的元素个数
for(int i=0;i<L.length;i++)
if (L.data[i] != x){
L.data[k] = L.data[i];
k++; //不等于x的元素增1
}
L.length = k; //顺序表L的长度等于k
}
//解法二:用k记录顺序表L中等于x的元素个数,边扫描L边统计k,并将不等于x的元素前移k个位置。
//扫描后修改L的长度。
void del_x_2(SqList& L, ElemType x) {
int k = 0, i = 0; //k记录值等于x的元素个数
while (i < L.length){
if (L.data[i] == x)
k++;
else
L.data[i - k] = L.data[i]; //当前元素前移k个位置
i++;
}
L.length = L.length - k; //顺序表L的长度递减
4.从有序顺序表中删除其值在给定值 s s s与 t t t之间(要求 s < t s<t s<t)的所有元素,若 s s s或 t t t不合理或顺序表为空,则显示出错信息并退出运行
//题目04
bool Del_s_t2(SqList& L, ElemType s, ElemType t) {
//删除有序顺序表L中值在给定值s与t之间的所有元素
int i, j;
if (s >= t || L.length == 0)
return false;
for (int i = 0; i < L.length && L.data[i] < s; i++);
//寻找值大于等于s的第一个元素
if (i <= L.length)
return false; //所有元素值均小于s,返回
for (j = i; j < L.length && L.data[j] <= t; j++);
//寻找值大于t的第一个元素
for (; j < L.length; i++, j++)
L.data[i] = L.data[j]; //前移,填补被删元素位置
L.length = i;
return true;
}
5.从顺序表中删除其值在给定值 s s s与 t t t之间(包含 s s s和 t t t,要求 s < t s<t s<t)的所有元素,若 s s s或 t t t不合理或顺序表为空,则显示出错信息并退出运行
//题目05
bool Del_s_t(SqList& L, ElemType s, ElemType t) {
//删除顺序表L中值在给定值s与t(要求s<t)之间的所有元素
int i, k = 0;
if (L.length == 0 || s >= t)
return false; //线性表为空或者s、t不合法,返回
for (int i = 0; i < L.length; i++){
if (L.data[i] >= s && L.data[i] <= t)
k++;
else
L.data[i - k] = L.data[i]; //当前元素前移k个位置
}//for
L.length -= k;
return true;
}
6.从有序顺序表中删除所有其值重复的元素,使表中所有元素的值均不同
//题目06
bool Delete_Same(SeqList& L) {
if (L.length == 0)
return false;
int i, j; //i存储第一个不相同的元素,j为工作指针
for (i = 0, j = 1; j < L.length; j++)
if (L.data[i] != L.data[j]) //查找下一个与上个元素值不同的元素
L.data[++i] = L.data[j]; //找到后,将元素前移
L.length = i + 1;
return true;
}
7.将两个有序顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表
//题目07
bool Merge(SeqList A, SeqList B, SeqList& C) {
//将有序顺序表A与B合并为一个新的有序顺序表C
if (A.length + B.length > C.MaxSize) //大于顺序表的最大长度
return false;
int i = 0, j = 0, k = 0;
while (i < A.length && j < B.length){ //进行比较,小的存入结果表
if (A.data[i] <= B.data[j])
C.data[k++] = A.data[i++];
else
C.data[k++] = B.data[j++];
}
while (i < A.length) //还有没比较完的顺序表
C.data[k++] = A.data[i++];
while (j < B.length)
C.data[k++] = B.data[j++];
C.length = k;
return k;
}
8.已知在一维数组 A [ m + n ] A[m+n] A[m+n]中一次存放两个线性表 ( a 1 , a 2 , a 3 , . . . , a m ) (a_1,a_2,a_3,...,a_m) (a1,a2,a3,...,am)和 ( b 1 , b 2 , b 3 , . . . , b n ) (b_1,b_2,b_3,...,b_n) (b1,b2,b3,...,bn),编写一个函数,将数组中两个顺序表的位置互换,即将 ( b 1 , b 2 , b 3 , . . . , b n ) (b_1,b_2,b_3,...,b_n) (b1,b2,b3,...,bn)放在 ( a 1 , a 2 , a 3 , . . . , a m ) (a_1,a_2,a_3,...,a_m) (a1,a2,a3,...,am)的前面
//题目08
typedef int DataType;
void Reverse(DataType A[], int left, int right, int arraySize) {
if (left >= right || right >= arraySize)
return;
int mid = (left + right) / 2;
for (int i = 0; i <= mid - left; i++){
DataType temp = A[left + i];
A[left + i] = A[right - i];
A[right - i] = temp;
}
}
void Exchange(DataType A[], int m, int n, int arraySize) {
Reverse(A, 0, m + n - 1, arraySize);
Reverse(A, 0, n - 1, arraySize);
Reverse(A, n, m + n - 1, arraySize);
}
9.线性表 ( a 1 , a 2 , a 3 , . . . , a n ) (a_1,a_2,a_3,...,a_n) (a1,a2,a3,...,an)中的元素递增有序且按顺序存储于计算机内,要求设计一个算法,完成用最少时间在表内查找数值为 x x x的元素,若找到,则将其与后续元素位置相交换,若找不到,则将其插入表中并使表中元素仍递增有序
//题目09
void SearchExchangeInsert(ElemType A[], ElemType x) {
int low = 0, high = n - 1, mid; //low和high指向顺序表下届和上届的下标
ElemType temp;
while (low <= high){
mid = (low + high) / 2; //找中间位置
if (A[mid] == x) break; //找到x,退出while循环
else if (A[mid] < x) low = mid + 1; //到中点mid的右半部去查
else high = mid - 1; //到中点mid的左半部去查
}
if (A[mid] == x && mid != n - 1){//若最后一个元素与x相等,则不存在与其后后继交换的操作
temp = A[mid];
A[mid] = A[mid + 1];
A[mid] = temp;
}
int i;
if (low > high) { //查找失败,插入数据元素x
for (i = n - 1; i > high; i--)
A[i + 1] = A[i]; //后移元素
A[i + 1] = x; //插入x
}
}
10.【2010统考真题】设将 n ( n > 1 ) n(n>1) n(n>1)个整数存放到一维数组 R R R中。设计一个在时间和空间都尽可能高效的算法。将 R R R中保存的序列循环左移 p ( 0 < p < n ) p(0<p<n) p(0<p<n)个位置
//题目10
void Reverse(int R[], int from, int to) {
int i, temp;
for (i = 0; i < (to - from + 1) / 2; i++){
temp = R[from + i];
R[from + i] = R[to - i];
R[to - i] = temp;
}
}
void Converse(int R[], int n, int p) {
Reverse(R, 0, p - 1);
Reverse(R, p, n - 1);
Reverse(R, 0, n - 1);
}
该算法时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( 1 ) O(1) O(1)
11.【2011统考真题】一个长度为 L ( L ≥ 1 ) L(L\ge1) L(L≥1)的升序序列 S S S,处在第 ⌈ L / 2 ⌉ \left \lceil L/2 \right \rceil ⌈L/2⌉个位置的数称为 S S S的中位数,两个序列的中位数是含他们所有元素的升序序列的中位数。现有两个等长升序序列 A A A和 B B B,设计一个在时间和空间两方面都尽可能高效的算法,找出两个序列 A A A和 B B B的中位数。
//题目11
int M_Search(int A[], int B[], int n) {
int s1 = 0, d1 = n - 1, m1;//序列A的首位数,末位数,中位数
int s2 = 0, d2 = n - 1, m2;//序列B的首位数,末位数,中位数
while (s1 != d1 || s2 != d2)
{
m1 = (s1 + d1) / 2;
m2 = (s2 + d2) / 2;
if (A[m1] == B[m2])
return A[m1];
if (A[m1] < B[m2]){//舍弃A中较小的一半,舍弃B中较大的一半
if ((s1 + d1) % 2 == 0){
s1 = m1;
d2 = m2;
}
else{
s1 = m1 + 1;
d2 = m2;
}
}
else{//舍弃A中较大的一半,舍弃B中较小的一半
if ((s2 + d2) % 2 == 0){
d1 = m1;
s2 = m2;
}
else{
d1 = m1;
s2 = m2 + 1;
}
}
}
return A[s1] < B[s2] ? A[s1] : B[s2];
}
该算法时间复杂度为 O ( log 2 n ) O(\log_2 n) O(log2n) ,空间复杂度为 O ( 1 ) O(1) O(1)
12.【2013统考真题】已知一个整数数列
A
=
(
a
0
,
a
1
,
.
.
.
,
a
n
−
1
)
A=(a_0,a_1,...,a_{n-1})
A=(a0,a1,...,an−1),其中
0
≤
a
i
<
n
(
0
≤
i
<
n
)
0\leq a_i<n(0\leq i<n)
0≤ai<n(0≤i<n)。
若存在
a
p
1
=
a
p
2
=
.
.
.
=
a
p
m
=
x
a_{p1}=a_{p2}=...=a_{pm}=x
ap1=ap2=...=apm=x且
m
>
n
/
2
(
0
≤
p
k
<
n
,
1
≤
k
≤
m
)
m>n/2(0\leq p_k <n,1\leq k\leq m)
m>n/2(0≤pk<n,1≤k≤m),则称
x
x
x为
A
A
A的主元素。
例如
A
=
(
0
,
5
,
5
,
3
,
5
,
7
,
5
,
5
)
A=(0,5,5,3,5,7,5,5)
A=(0,5,5,3,5,7,5,5),则
5
5
5为主元素;
又如
A
=
(
0
,
5
,
5
,
3
,
5
,
1
,
5
,
7
)
A=(0,5,5,3,5,1,5,7)
A=(0,5,5,3,5,1,5,7),则
A
A
A中没有主元素。
假设
A
A
A中的
n
n
n个元素保存在一个一维数组中,请设计一个尽可能高效的算法,找出
A
A
A的主元素。若存在主元素,则输出该元素;否则输出
−
1
-1
−1。
//题目12
int Majority(int A[], int n) {
int i, c, count = 1; //c用来保存候选主元素,count用来计数
c = A[0]; //设置A[0]为候选主元素
for (i = 1; i < n; i++) //查找候选主元素
if (A[i] == c)
count++;
else
if (count > 0) //不是候选主元素
count--;
else {
c = A[i]; //更换候选主元素,重新计数
count = 1;
}
if (count > 0)
for (i = count = 0; i < n; i++)//统计候选主元素的实际出现次数
if (A[i] == c)
count++;
if (count > n / 2)
return c; //确定候选主元素
else
return -1; //不存在主元素
该算法时间复杂度为 O ( n ) O(n) O(n) ,空间复杂度为 O ( 1 ) O(1) O(1)
13.【2018统考真题】给定一个含
n
(
n
≥
1
)
n(n\ge 1)
n(n≥1)个整数的数组,请设计一个在时间上尽可能高效的算法,找出数组中未出现的最小正整数。
例如,数组
{
−
5
,
3
,
2
,
3
}
\{-5,3,2,3\}
{−5,3,2,3}中未出现的最小正整数为
1
1
1;
数组
{
1
,
2
,
3
}
\{1,2,3\}
{1,2,3}中未出现的最小正整数为
4
4
4。
//题目13
int findMissMin(int A[], int n) {
int i, * B; //B为标记数组
B = (int*)malloc(sizeof(int) * n);
memset(B, 0, sizeof(int) * n); //赋初值为0
for (i = 0; i < n; i++)
if (A[i] > 0 && A[i] <= n) //若A[i]的值介于1~n,则标记数组B
B[A[i] - 1] - 1;
for (i = 0; i < n; i++) //扫描数组B,找到目标值
if (B[i] == 0)
break;
return i + 1;
}
该算法时间复杂度为 O ( n ) O(n) O(n) ,空间复杂度为 O ( n ) O(n) O(n)
14.【2020统考真题】定义三元组
(
a
,
b
,
c
)
(a,b,c)
(a,b,c)(
a
、
b
、
c
a、b、c
a、b、c均为正数)的距离
D
=
∣
a
−
b
∣
+
∣
b
−
c
∣
+
∣
c
−
a
∣
D= \left| a-b \right|+\left| b-c \right|+\left| c-a \right|
D=∣a−b∣+∣b−c∣+∣c−a∣。给定
3
3
3个非空整数集合
S
1
S_1
S1、
S
2
S_2
S2和
S
3
S_3
S3,按圣墟分别存储在
3
3
3个数组中。请设计一个尽可能高效的算法,计算并输出所有可能的三元组
(
a
,
b
,
c
)
(
a
∈
S
1
,
b
∈
S
2
,
c
∈
S
3
)
(a,b,c)(a\in S_1,b \in S_2, c \in S_3)
(a,b,c)(a∈S1,b∈S2,c∈S3)中的最小距离。
例如
S
1
=
{
−
1
,
0
,
9
}
,
S
2
=
{
−
25
,
−
10
,
10
,
11
}
,
S
3
=
{
2
,
9
,
17
,
30
,
41
}
S_1=\{-1,0,9\},S_2=\{-25,-10,10,11\},S_3=\{2,9,17,30,41\}
S1={−1,0,9},S2={−25,−10,10,11},S3={2,9,17,30,41},则最小距离为
2
2
2,相应的三元组为
(
9
,
10
,
9
)
(9,10,9)
(9,10,9)。
//题目14
#define INT_MAX 0x7fffffff
int abs_(int a) {//计算绝对值
if (a < 0)
return -a;
else
return a;
}
bool xls_min(int a, int b, int c) {//a是否是a、b、c三个数中的最小值
if (a <= b && a <= c)
return true;
else
return false;
}
int findMinofTrip(int A[], int n, int B[], int m, int C[], int p) {
//D_min用于记录三元组的最小距离,初值赋为INT_MAX
int i = 0, j = 0, k = 0, D_min = INT_MAX, D;
while (i < n && j < m && k < p && D_min>0) {
D = abs_(A[i] - B[j]) + abs_(B[j] - C[k]) + abs_(C[k] - A[i]); //计算D
if (D < D_min)
D_min = D; //更新D
if (xls_min(A[i], B[j], C[k])) //更新a
i++;
else if (xls_min(B[j], C[k], A[i]))
j++;
else
k++;
}
return D_min;
}
设
n
=
(
∣
S
1
∣
+
∣
S
2
∣
+
∣
S
3
∣
)
n=(\left| S_1 \right| +\left| S_2 \right| +\left| S_3 \right| )
n=(∣S1∣+∣S2∣+∣S3∣)
该算法时间复杂度为
O
(
n
)
O(n)
O(n) ,空间复杂度为
O
(
1
)
O(1)
O(1)
链表综合应用
1.设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点
//题目01
void RDel_x(LinkList& L, ElemType x) {
//递归实现在单链表L中删除值为x的结点
LNode* p;
if (L == NULL)
return;
if (L->data == x) {
p = L;
L = L->next;
free(p);
RDel_x(L, x);
}
else
RDel_x(L->next, x);
}
该算法借助一个递归工作栈,深度为 O ( n ) O(n) O(n),时间复杂度为 O ( n ) O(n) O(n)
2.在带头结点的单链表L中,删除所有值为x的结点,并释放其空间,假设值为x的结点不唯一
//题目02
//解法一:用p从头至尾扫描单链表,pre指向*p结点的前驱
//若p所指结点的值为x,则删除,并让p移向下一个节点
//若p所指结点的值不为x,则让pre、p指针同步后移一个结点
void Del_x_1(LinkList& L, ElemType x) {
LNode* p = L->next, * pre = L, * q;
while (p != NULL) {
if (p->data == x) {
q = p;
p = p->next;
pre->next = p;
free(q);
}
else {
pre = p;
p = p->next;
}
}
}
//解法二
//采用尾插法建立单链表
//用p指针扫描L的所有结点,当其值不为x时,将其链接到L之后
//当其值为x时,释放掉
void Del_x_2(LinkList& L, ElemType x) {
LNode* p = L->next, * r = L, * q;
while (p != NULL) {
if (p->data != x) {
r->next = p;
r = p;
p = p->next;
}
else {
q = p;
p = p->next;
free(q);
}
}
r->next = NULL;
}
3.设L为带头结点的单链表,编写算法实现从尾到头反向输出每个结点的值
//题目03
//解法一:
//书中给出的解法是使用递归函数,代码如下
void ReversePrint(LinkList& L) {
//从尾到头输出单链表L中每个结点的值
if (L->next != NULL)
ReversePrint(L->next);
if (L != NULL)
printf("%d",L->data);//print函数应该根据ElemType自行定义
}
void ReversePrintIgnoreHead(LinkList& L) {
if (L->next != NULL)
ReversePrint(L->next);
}
//解法二:
//先进后出FILO的思路,很容易想到使用栈来进行实现
4.试编写在带头结点的单链表L中删除一个最小值结点的高效算法(假设最小值点是唯一的)
//题目04
//删除最小值结点的问题很明显是删除特定结点和寻找最小值结点的结合
//在寻找最小值结点时,我们遍历一遍单链表即可
//删除特定结点时,要使用到指向该特定结点的指针,以及指向该结点的前驱结点的指针
//结合二者的高效算法,应该在遍历的同时,不仅留意最小值,同时保留指针指向结点的前驱结点
LinkList DeleteMin(LinkList& L) {
//使用p来进行遍历,pre指向*p的前驱结点
//min来指向最小值结点,min_pre来指向最小值结点的前驱结点
LNode* pre = L, * p = pre->next;
LNode* minpre = L, * min = p;
while (p != NULL) {
if (p->data < min->data) {
min = p;
minpre = pre;
}
pre = p;
p = p->next;
}
//while循环结束时,已找到最小值结点
minpre->next = min->next;//删除最小值结点
free(min);
return L;
}
该算法时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( 1 ) O(1) O(1)
5.试编写算法将带头结点的单链表就地逆置。就地指辅助空间复杂度为 O ( n ) O(n) O(n)
//题目05
//由于要求就地逆置,因此只能进行指针的操作
//解法一
//将头结点取下,从第一个结点开始,使用头插法方式进行链接
LinkList Reverse_1(LinkList& L) {
LNode* p, * r;//p为工作指针,r为p的后继,防止在操作过程中断链
p = L->next;
r = p->next;
L->next = NULL;//取下头结点
while (p != NULL) {
r = p->next;
p->next = L->next;
L->next = p;
p = r;
}
return L;
}
//解法二
//从头结点开始,每个结点按顺序进行指针的操作来达到逆置的目的
LinkList Reverse_2(LinkList& L) {
LNode* pre,*p=L->next, * r=p->next;//p为工作指针,r为p的后继,pre为p的前驱,r防止在操作过程中断链
p->next = NULL;
while (r!= NULL) {
pre = p;
p = r;
r = r->next;
p->next = pre;
}
L->next = p;
return L;
}
这两个算法的时间复杂度均为 O ( n ) O(n) O(n),空间复杂度均为 O ( 1 ) O(1) O(1)
6.有一个带头结点的单链表L,设计一个算法使其元素递增有序
//题目06
//解法一
//首先拿出一个非头结点的结点,与头结点构成一个单链表
//然后将原单链表的剩余部分,依次进行有序插入
//最后应使新链表data域递增
void Sort(LinkList& L) {
LNode* p = L->next,*pre;
LNode* r = p->next;
p->next = NULL;
p = r;
while (p != NULL) {
r = p->next;
pre = L;
while (pre->next != NULL && pre->next->data < p->data)
pre = pre->next;
p->next = pre->next;
pre->next = p;
p = r;
}
}
//解法二 //空间换时间
//遍历一遍链表,把data域复制到一个数组中,对数组使用排序
//排序后再复制回去
7.设在一个带表头结点的单链表中所有元素结点的数据值无序,是编写一个函数,删除表中所有介于给定的两个值(作为函数参数给出)之间的元素(若存在)
//题目07
//遍历,逐个检查
void RangeDelete(LinkList& L, int min, int max) {
LNode* pr = L, * p = L->next;
while(p!=NULL)
if (p->data>min && p->data < max) {
pr->next = p->next;
free(p);
p = pr->next;
}
else {
pr = p;
p = p->next;
}
}
8.给定两个单链表,编写算法找出两个链表的公共结点
//题目08
//对公共结点的理解:并非是只有data域的值相等,next域也要相同,即这两个单链表形如'Y'
//解法一
//遍历,对于链表A,依次遍历每个结点,对于每个A上的结点,遍历一遍链表B进行匹配,直到找到了相同的结点
//解法二
//对于链表A,长度为len1 ;对于链表B,长度为len2
//如果A与B有公共结点,则至少为尾结点相同
//令k=abs(len1-len2);
//在长的那个链表先遍历k个结点,再进行A与B的同步遍历
LinkList SearchFirstCommonNode(LinkList L1, LinkList L2) {
//在线性的时间内找到两个单链表的第一个公共结点
int len1 = GetLength(L1);
int len2 = GetLength(L2);
int dist;
LinkList longList, shortList;
if (len1 > len2) {
longList = L1->next;
shortList = L2->next;
dist = len1 - len2;
}
else {
longList = L2->next;
shortList = L1->next;
dist = len2 - len1;
}
//dist = len1 - len2;
//bool flag = dist > 0;
//longList = flag ? L1->next : L2->next;
//shortList = flag ? L2->next : L1->next;
//dist = flag ? dist : -dist;
while (dist--) //走dist个结点
longList = longList->next;
while (longList != NULL) {
if (longList == shortList)
return longList;
else {
longList = longList->next;
shortList = shortList->next;
}
}
return NULL;
}
09.给定一个带表头结点的单链表,设head为头指针,结点结构为(data,next),data为整形元素,next为指针,试写出算法:按递增次序输出单链表中各结点的数据元素并释放结点所占的存储空间(要求:不允许使用数组作为辅助空间)
//题目09
//遍历链表,每次遍历找出链表中最小值元素,输出并释放空间
//循环直至链表为空,最后释放头结点所占存储空间
void Print_FreeMin(LinkList& head) {
while (head->next != NULL) {
LNode* pre = head;
LNode* p = pre->next;
LNode* u;
while (p->next != NULL) {
if (p->next->data < pre->next->data)
pre = p;
p = p->next;
}
printf("%d",pre->next->data);
u = pre->next;
pre->next = u->next;
free(u);
}
free(head);
}
10.将一个带头结点的单链表A分解为两个带头结点的单链表A和B,使得A表中含有原表中序号为奇数的元素,B表中含有原表中序号为偶数的元素,且保持其相对位置不变
//题目10
//
LinkList Divide(LinkList& A) {
//将表A中的结点按照序号的奇偶性分解到A和B两个链表中
int i = 0;
LinkList B = (LinkList)malloc(sizeof(LNode));
B->next = NULL;
LNode* ra = A;//尾指针
LNode* rb = B;//尾指针
LNode* p=A->next;//工作指针,指向待分解的结点
A->next = NULL;
while (p != NULL) {
i++;
if (i % 2 == 0) {//处理偶结点
rb->next = p;//在B表尾插入新结点
rb = p; //rb指向新的尾结点
}
else { //处理奇结点
ra->next = p;//在A表尾插入新结点
ra = p; //ra指向新的尾结点
}
p = p->next;
}
ra->next = NULL;
rb->next = NULL;
return B;
}
11.设 C = { a 1 , b 1 , a 2 , b 2 , . . . , a n , b n } C=\{a_1,b_1,a_2,b_2,...,a_n,b_n\} C={a1,b1,a2,b2,...,an,bn}为线性表,采用带头结点的hc单链表存放,设计一个就地算法,将其拆分为两个线性表,使得 A = { a 1 , a 2 , . . . , a n } A=\{a_1,a_2,...,a_n\} A={a1,a2,...,an}, B = { b 1 , b 2 , . . . , b n } B=\{b_1,b_2,...,b_n\} B={b1,b2,...,bn}
12.在一个递增有序的线性表中,有数值相同的元素存在,若存储方式为单链表,设计算法去掉数值相同的元素,使表中不再有重复元素。
例如,
(
7
,
10
,
10
,
21
,
30
,
42
,
42
,
42
,
51
,
70
)
(7,10,10,21,30,42,42,42,51,70)
(7,10,10,21,30,42,42,42,51,70)将变为
(
7
,
10
,
21
,
30
,
42
,
51
,
70
)
(7,10,21,30,42,51,70)
(7,10,21,30,42,51,70)
13.假设有两个按元素值递增次序排列的线性表,均以单链表形式存储,请编写算法将这两个单链表归并为一个按元素值递减次序排列的单链表,并要求利用原来两个单链表的结点存放归并后的单链表
14.设A和B是两个单链表(带头结点),其中元素递增有序,设计一个算法从A和B中的公共元素产生单链表C,要求不破坏A、B的结点
15.已知两个链表A和B分别表示两个集合,其元素递增排列,编写函数,求A与B的交集,并存放于A链表中
16.两个整数序列 A = a 1 , a 2 , a 3 , . . . , a m A=a_1,a_2,a_3,...,a_m A=a1,a2,a3,...,am和 B = b 1 , b 2 , b 3 , . . . , b n B=b_1,b_2,b_3,...,b_n B=b1,b2,b3,...,bn已经存入两个单链表中,设计算法,判断序列B是否是序列A的连续子序列
17.设计一个算法用于判断带头结点的循环双链表是否对称
18.有两个循环单链表,链表头指针分别为h1和h2,编写一个函数将链表h2链接到链表h1之后,要求连接后的链表仍然保持循环链表的形式
19.设有一个带头结点的循环单链表,其结点值均为正整数,设计一个算法,反复找出单链表中结点值最小的结点并输出,然后将该结点从中删除,知道单链表空位置,再删除表头结点
20.设头指针为L的带有表头结点的非循环双向链表,其每个结点中除有pred(前驱指针)、data(数据)、next(后继指针)域外,还有一个访问频度域freq。在链表被启用前,其值均初始化为零。每当在链表中进行一次Locate(L,x)运算时,令元素值为x的结点中freq域的值增1,并使此链表中结点保持按访问频度非增的顺序排列,同时最近访问的结点排在频度相同的结点前面,以便频繁访问的结点总是靠近表头。
试编写符合上述要求的Locate(L,x)运算的算法,该运算为函数过程,返回找到结点的地址,类型为指针型
21.单链表有环,是指单链表的最后一个结点的指针指向了链表中的某个结点(通常单链表的最后一个结点的指针域是空的)。试编写算法判断单链表是都存在环
22.已知一个带有表头结点的单链表,结点结构为[data|link]。假设该链表只给出了头指针list,在不改变链表的前提下,请设计一个尽可能高效的算法,查找链表中倒数第k个位置上的结点(k为正整数)。若查找成功,算法输出该结点的data域的值,并返回1;否则,只返回0
23.假定采用带头结点的单链表保存单词,当两个单词有相同的后缀时,可共享相同的后缀存储空间,例如,"loading"和"being"共享相同的后缀存储空间。
设str1和str2分别指向两个单词所在单链表的头结点,链表结点的结构为[data|next],请设计一时间上尽可能高效的算法,找出由str1和str2所指向的两个链表共同后缀的起始位置。
24.用单链表保存m个整数,结点的结构为 [ d a t a ] [ l i n k ] [data] [link] [data][link],且 ∣ d a t a ∣ ≤ n |data|\le n ∣data∣≤n(n为正整数)。现要求设计一个时间复杂度尽可能高效的算法,对于链表中data的绝对值相等的结点,仅保留第一次出现的结点而删除其余绝对值相等的结点。
25.设线性表 L = { a 1 , a 2 , a 3 , . . . , a n − 2 , a n − 1 , a n } L=\{a_1,a_2,a_3,...,a_{n-2},a_{n-1},a_n\} L={a1,a2,a3,...,an−2,an−1,an}采用带头结点的单链表保存,链表中的结点定义如下
typedef struct node{
int data;
struct node*next;
}NODE;
请设计一个空间复杂度为 O ( 1 ) O(1) O(1)且时间上尽可能高效的算法,重新排列L中的各结点,得到线性表 L ′ = { a 1 , a n , a 2 , a n − 1 , a 3 , a n − 2 , . . . } L'=\{a_1,a_n,a_2,a_{n-1},a_3,a_{n-2},...\} L′={a1,an,a2,an−1,a3,an−2,...}