一、线性表
1.1顺序表
1、删除最小的元素,空出的元素由最后一位填补
bool Del_Min(SqList &L, ElemType &value){
if(L.length == 0)
return false;
value == L.data[0];
int pos = 0;
for(int i = 1; i < L.length; i++)
if(L.data[i] < value){
value = L.data[i];
pos = i;
}
L.data[pos] = L.data[L.length-1];
L.length--;
return true;
}
2、所有元素逆置
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[L.length-i-1] = temp;
}
}
3、删除所有值为x的元素,时间复杂度为O(n),空间复杂度为O(1)
void Del_X_1(SqList &L, ElemType x){
int k = 0;
for(int i = 0; i < L.length; i++)
if(L.data[i] != x)
L.data[k++] = L.data[i];
L.length=k;
}
void Del_X_2(SqList &L, Elemtype x){
int k = 0, i = 0;
while(i < L.length){
if(L.data[i] == x)
k++;
else
L.data[i-k] = L.data[i];
}
L.length -= k;
}
4、从有序表中删除其值在给定值s与t之间的所有元素(s<t)
bool Del_s_t(SqList &L, ElemType s, ElemType t){
int i, j;
if(s >= t || L.length == 0)
return false;
for(i = 0; i < L.length&& L.data[i] < s; i++);
if(i >= L.length)
return false;
for(j = i; j < L.length&&L.data[i] < t; j++);
for(;j < L.length; i++, j++)
L.data[i] = L.data[j];
L.length = i;
return true;
}
5、顺序表中删除其值在给定值s与t之间的所有元素(包括s和t)
void Del_s_t2(SqList &L, ElemType s, ElemType t){
if(s > t || L.length == 0)
return false;
int k = 0;
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];
}
L.length -= k;
return true;
}
6、有序顺序表中删除所有值重复的元素
bool Del_Repeat_Value(SqList &L){
if(L.length == 0)
return false;
int i=0, j=1;
for(;j<L.length;j++){
if(L.data[i] != j)
L.data[++i] = L.data[j];
}
L.length = i+1;
return true;
}
7、将两个有序顺序表合并为一个
bool Merge(SqList &A, SqList &B, SqList &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 true;
}
8、将数组A[m+n]中的两个线性表(a1,a2,…,am)和(b1,b2,…,bm)位置互换变为(b1,b2,…,bm)和(a1,a2,…,am)
//使用2中的Reverse函数分别对线性表a、b以及A转换即可
9、用最短的时间在顺序表中查找x,并且与后面一个元素互换位置,找不到就插入表中使其任然有序
void SearchExchangeInsert(SqList &L, ElemType x){
int low = 0, high = L.length - 1, mid;
while(low <= high){
mid = (low+high)/2;
if(A[mid] == x)
break;
else if(A[mid] < x)
low = mid + 1;
else
high = mid - 1;
}
if(A[mid] == x && mid != n-1)
t=A[mid];
A[mid]=A[mid+1];
A[mid+1]=t;
if(low > high){
for(i=n-1;i>high;i++)
A[i+1] = A[i];
A[i+1] = x;
}
}
10、
//与第八题思路一致,时间复杂度O(n),空间复杂度O(1)
11、寻找两个升序序列的中位数
//1、分别寻找两个序列的中位数a和b
//2、如果a < b,那么舍弃a左边那部分(因为a左边比a小,那么左边<a<b,中位数必然不会出现在两个序列合并后的a的左半边),舍弃b右边那部分(同理,中位数也不会出现在两个数列合并后的b的右半边,因为偏右)
12、
/*
①选取候选的主元素。依次扫描所给数组中的每个整数,将第个遇到的整数 Num保存到
C中,记录Num的出现次数为1;若遇到的下一个整数仍等于Num, 则计数加1,否则
计数减1;当计数减到0时,将遇到的下一个整数保存到c中,计数重新记为1,开始
新一轮计数,即从当前位置开始重复上述过程,直到扫描完全部数组元素。
②判断c中元素是否是真正的主元素。再次扫描该数组,统计C中元素出现的次数,若大
于n/2,则为主元素:否则,序列中不存在主元素。
*/
13、空间换时间,设置辅助数组,检查没有出现的元素
1.2链表
1、设计递归算法,删除不带头节点的单链表L中所有值为x的节点
void Del_x(LinkList &L, ElemType x){
LNode *p;
if(L==NULL)
return;
if(L->data==x){
p=L;
L=L->next;
free(p);
Del_x(L,x);
}
else
Del_x(L->next,x);
}
2、在带头结点的单链表L中,删除所有值为x的节点,并释放其空间
void Del_x_1(LinkList &L, ElemType x){
if(L->next == NULL)
return;
LNode *p = L->next, *prep = L;
while(p!=NULL){
if(p->data == x){
LNode *q = p;
prep->next=p->next;
p = p->next;
free(q);
}
else{
prep = p;
p = p->next;
}
}
}
3、L为带头结点的单链表,编写算法实现从尾到头反向输出每个节点的值
void Reverse_Print(LinkList &L){
LNode *p = L->next;
if(p->next != NULL)
Reverse_Print(p->next);
else
print(p->data);
}
4、删除带头结点的单链表L中值最小的结点的高效算法
//minPrep,minvalue存储当前搜索过的所有节点中最小的值以及其前驱节点,prep和p存储当前结点以及前驱结点,整个单链表过一遍之后,用minPrep
//删除最小结点
void Del_Min(LinkList &L){
LNode *minPrep = L, *prep = L, *p = L.next;
ElemType minValue = p->data;
while(p!=NULL){
if(p->data<minalue){
minPrep = prep;
minValue = p->data;
}
prep = p;
p = p->next;
}
minPrep->next = minPrep->next->next;
}
5、将带头结点的单链表就地逆置
//采用头插法建立单链表,然后遍历新的单链表
void Reverse(LinkList &L){
LNode *p = L->next, *q = p->next;
while(p!=NULL){
p->next = L->next;
L.next = p;
p = q;
if(q!=NULL)
q = q->next;//处理最后一个节点,防止空指针异常
}
}
6、带头结点单链表L,设计算法使其元素递增有序
//遍历一遍放到数组中,快速排序,再放到单链表中O(nlog2n)
//直接插入排序思想O(n2)
7、删除无序单链表内值处于给定区间内的结点
//设置prep和p,如果p的值在区间内,就用prep删除p结点
void Del_Range_Value(LinkList &L, ElemType s, ElemType t){
LNode *prep = L, *p = L->next;
while(p != NULL){
if(p->data > s && p->data < t){
p = p->next;
prep->next = p;
}
else{
prep = p;
p = p->next;
}
}
}
8、找出两个给定单链表的公共节点
//第一个结点相同之后,之后的结点必然相同
LNode Find_Common-LNode(LinkList &A, LinkList &B){
int numA = 0, numB = 0;
LNode *pNodeA = A, *pNodeB = B;
while(pNodeA != NULL){
numA++;
pNodeA = pNodeA->next;
}
while(pNodeB != NULL){
numB++;
pNodeB = pNodeB->next;
}
*pNodeA = A, *pNodeB = B;
if(numA > numB){
int count = numA-numB;
while(count != 0){
if(pNodeA == pNodeB)
return pNodeA;
else{
pNodeA = pNodeA->next;
pNodeB = pNodeB->next;
}
}
return NULL;
}
if(numA < numB){
int count = numB-numA;
while(count != 0){
if(pNodeA == pNodeB)
return pNodeA;
else{
pNodeA = pNodeA->next;
pNodeB = pNodeB->next;
}
}
return NULL;
}
}
9、按递增次序输出带头结点单链表中各节点的数据
//根据第6题排序之后再输出
10、将单链表A分成两个带头单链表A和B,使A中含有原链表中序号为奇数的元素,B中含有原链表中序号为偶数的元素
//设置计数器count,判断当前节点序号是偶数还是奇数
void Devide_List(LinkList &A, LinkList &B){
LNode *prep=A, *p = A->next, *b = B, *q;
int count = 0;
while(p!=NULL){
count++;
if(count%2!=0){
prep = p;
p = p->next;
}
else{
q = p;
prep->next = p->next;
p = p->next;
//尾插法
q->next = b->next;
b->next = q;
b = q;
}
}
}
11、设计就地算法将{a1,b2,…,an,bn}拆分为{a1,a2,…,an}和{bn,…,b2,b1}
//按照第10题的思路,a序列采用尾插法建立单链表,b序列采用头插法建立单链表
void Devide_List(LinkList &A, LinkList &B){
LNode *prep=A, *p = A->next, *q;
int count = 0;
while(p!=NULL){
count++;
if(count%2!=0){
prep = p;
p = p->next;
}
else{
q = p;
prep->next = p->next;
p = p->next;
//头插法
q->next = B->next;
B->next = q;
}
}
}
12、删除递增有序的单链表中的重复值的元素
//设置prep和p,prep指向当前已经搜索过的没有重复元素的最后一个,p向后寻找,如果当前元素的值和prep不相同,则prep->next=p;p=p->next;
//如果相同p向后寻找,直到p==NULL
void Del_Repeat_Value(LinkList &L){
LNode *prep = L->next, p = prep->next;
while(p!=NULL){
if(prep->data == p->data){
LNode *q = p;
p = p->next;
prep->next = p;
free(q);
}
else{
prep = p;
p = p->next;
}
}
}
13、将两个元素递增的线性表合并成一个元素递减的线性表
//同时比较大小,小的使用头插法插入,最后剩余的再使用头插法
void Combine_List(LinkList &A, LinkList &B, LinkList &C){
LNode *pa = A->next, pb = B->next, *q;
while(pa&&pb){
if(pa->data<=pb->next){
q = pa;
pa = pa->next;
q->next = C->next;
C->next = q;
}
if(pa->data>pb->next){
q = pb;
pb = pb->next;
q->next = C->next;
C->next = q;
}
}
}
14、A和B是两个带头结点的单链表,其中元素递有序,设计算法从A和B中产生单链表C,不破坏A和B的结点
void Get_Common(LinkList &A, LinkList &B, LinkList &C){
LNode *pa = A->next, *pb = B->next, *pc = C, *r;
while(pa&&pb){
if(pa<pb)
pa = pa->next;
else if(pa>pb)
pb=pb->next;
else{
r = (LNode *)malloc(sizeof(LNode));
r->data = pa->data;
pc->next = r;
pc = r;
pa = pa->next;
pb = pb->next;
}
}
pc->next = NULL;
}
15、已知两个链表A和B分别表示两个集合,其元素递增排列。编制函数,求A与B的交集,并存放于A链表中。
void Get_Common_1(LinkList &A, LinkList &B){
LNode *pa = A->next, *pb = B->next, *s, pc = A;
while(pa&&pb){
if(pa->data<pb->data){
s = pa;
pa = pa->next;
free(s);
}
else if(pa->data>pb->data){
s = pb;
pb = pb->next;
free(s);
}
else{
pc->next = pa;
pc = pa;
pa = pa->next;
s = pb;
pb = pb->next;
free(s);
}
}
while(pa){
s = pa;
pa = pa->next;
free(s);
}
while(pb){
s = pb;
pb = pb->next;
free(s);
}
}
16、两个整数序列A=a1,a2, a3,…,am和B=b1, b2, b3,…, bn已经存入两个单链表中,设计一个算法,判断序列B是否是序列A的连续子序列。
bool Is_Pattern(LinkList &A, LinkList &B){
LinkList *pa = A->next, *pb = A->next, *pr;
while(pa&&pb){
if(pa->data != pb->data)
pa = pa->next;
if(pa->data == pb->data){
pr = pa;
pa = pa->next;
pb = pb->next;
pr = pa;
while(pa&&pb){
if(pa->data!=pb->data){
pa = pr;
pb = A->next;
break;
}
else{
pa = pa->next;
pb = pb->next;
}
}
if(!pa&&pb)
return false;
return true;
}
}
}
17、设计一个算法用于判断带头结点的循环双链表是否对称。
bool Is_Symmetry(DLinkList &L){
LNode *p = L->next;
int count = 1;
while(p != L){
count++;
}
LNode *left = L->prior, *right = L->next;
if(count%2==0){
while((count/2)--){
if(left->data == right->data){
left = left->prior;
right = right->next;
}
else{
break;
}
}
return true;
}
else{
while(left!=right){
if(left->data == right->data){
left = left->prior;
right = right->next;
}
else{
break;
}
}
}
}
18、有两个循环单链表,链表头指针分别为h1和h2,编写一个函数将链表h2链接到链表h1之后,要求链接后的链表仍保持循环链表形式。
LinkList Combine(LinkList &h1, LinkList &h2){
LNode *p = h1, *q = h2;
while(p->next){
p = p->next;
}
p->next = h2;
while(q->next){
q = q->next;
}
q->next = h1;
return h1;
}
19、设有一个带头结点的循环单链表,其结点值均为正整数。设计一个算法,反复找出单链表中结点值最小的结点并输出,然后将该结点从中删除,直到单链表空为止,再删除表头结点。
void Print_Min_Value(LinkList &L){
while(L->next!=L){
LNode *p = L->next, *minPrep = L;
int minValue = L->next->data;
while(p->next!=L){
if(p->next->data<minValue){
minPrep = p;
minValue = p->next->data;
}
}
LNode *s = minPrep->next;
minPrep->next = minPrep->next->next;
print(s->data);
free(s);
}
free(L);
}
20、设头指针为L的带有表头结点的非循环双向链表,其每个结点中除有pred(前驱指针)、data (数据)和next (后继指针)域外,还有一个访问频度域freq。在链表被启用前,其值均初始化为零。每当在链表中进行一次Locate (L,x)运算时,令元素值为x的结点中freq域的值增1,并使此链表中结点保持按访问频度非增(递减)的顺序排列,同时最近访问的结点排在频度相同的结点前面,以便使频繁访问的结点总是靠近表头。试编写符合.上述要求的Locate(L,x)运算的算法,该运算为函数过程,返回找到结点的地址,类型为指针型。
LNode Locate(LinkList &L, ElemType x){
LNode *p = L->next;
while(p!=NULL){
if(p->data == x){
p->freq+=1;
}
}
if(p==NULL)
return NULL;
LNode *s = p;
p = p->pred;
p->next = s->next;
while(p!=L){
if(p->freq>s->freq){
s->next = p->next;
p->next->pred = s;
p->next = s;
s->pred = p;
}
}
if(p==L&&s->next==NULL&&s->pred==NULL){
s->next = L->next;
L->next->pred = s;
L-next = s;
s->pred = L;
}
return s;
}