一、线性表
1、从顺序表中删除具有最小值的元素,并由函数返回被删除元素的值,空出的位置由最后一个元素填补
# define MaxSize 50
// 顺序表类型定义
typedef struct SqList{
ElemType data[MaxSize];
int length;
}SpList;
/*算法思想: 搜索整个顺序表,查找最小元素并记住其位置,搜索结束后用最后一个元素填补空出的最小值的位置 */
// 删除最小元素
bool Del_min(SpList &L, ElemType &value) {
if(L.length == 0){
return false; // 表空,返回false
}
value = L.data[0]; // 假设第一个位置就是最小值
int pos = 0 ; // 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--; // 表长 -1
return true;
}
2、线性表元素逆置
# define MaxSize 50
// 顺序表类型定义
typedef struct SqList{
ElemType data[MaxSize];
int length;
}SpList;
/*算法思想:将第一个元素和最后一个元素交换,第二个元素和倒数第二个元素交换,以此类推*/
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-1-i];
L.data[L.length-1-i] = temp;
}
}
3、删除线性表中所有值为 x 的元素
# define MaxSize 50
// 顺序表类型定义
typedef struct SqList{
ElemType data[MaxSize];
int length;
}SpList;
/*算法思想:遍历顺序表,将不是 x 的元素保留下来 (删除所有 x 的元素)*/
void del_X(SqList &L,ElemType x){
int k = 0; // 用来记录值不等于 x 的个数
for(int i = 0;i<L.length;i++){ // 遍历顺序表
if(L.data[i] != x){
L.data[k] = L.data[i]; // 将不等于x的元素保留下来
k++;
}
}
L.length = k; // 顺序表的长度 = k
}
4、从顺序表中删除其值在给定值 x ~ t 之间的所有元素(x<t)
# define MaxSize 50
// 顺序表类型定义
typedef struct SqList{
ElemType data[MaxSize];
int length;
}SpList;
// 方法一、
/*算法思想:将L.data[i] < s 和L.data[i] > t 的元素保留 */
bool Del_s_t(SqList &L,ElemType s,ElemType t){
if(L.length == 0){ // 如果顺序表为空,返回false
return false;
}
int k = 0; // 保存值小于 s ,值大于 t 的元素个数
for(int i = 0;i<L.length;i++){
if(L.data[i]<s || L.data[i] >t){
L.data[k] = L.data[i];
k++;
}
}
L.length = k;
return true;
}
// 方法二、
/*算法思想:扫描顺序表,将位于 s~t 之间数的个数记为 k 个,将不是s~t之间的数向前移 k 个单位*/
bool Del_s_t(SqList &L,ElemType s,ElemType t){
if(L.length == 0 || s>t){ // 如果顺序表为空,返回false
return false;
}
int k = 0; // 保存值小于 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个单位
}
}
L.length = L.length - k;
return true;
}
5、从有序表中,删除所有值重复的元素
# define MaxSize 50
// 顺序表类型定义
typedef struct SqList{
ElemType data[MaxSize];
int length;
}SpList;
/*算法思想:第一个元素肯定不重复,两个指针 i,j 依次向后扫描,元素不重复就保留,重复的元素不保留*/
bool Delete_same(SqList &L){
if(L.length == 0){ // 如果顺序表为空,返回false
return false;
}
int i; // 存储第一个不重复元素
int j; // 遍历线性表指针
for(i = 0,i = 1;j<L.length;j++){
if(L.data[i] != L.data[j]){
//i++;
//L.data[i] = L.data[j];
L.data[++i] = L.data[j]; // 将不重复的元素保留
}
}
L.length = i+1;
return true;
}
6、将两个有序顺序表合并为一个新的有序顺序表
// 顺序表类型定义
typedef struct SqList{
ElemType *data;
int length,MaxSize;
}SpList;
/*算法思想:将A,B中较小的元素依次插入C中,如果A或B中还有元素剩余,将剩余元素依次插入C中*/
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++]; // 将更小的元素存入 C 中
//C.data[k] = A.data[i];
//k++;
//i++;
}
else(
C.data[k++] = B.data[j++];
)
}
while(i<A.length){ // A的长度更长,有元素剩余
C.data[k++] = A.data[i++];
}
while(j<B.length){ // B的长度更长
C.data[k++] = B.data[j++];
}
C.length = k;
return true;
}
7、将线性表中(a1,a2,a3,……,am,b1,b2,b3,……,bm) ,a1,a2,a3,……,am的位置和b1,b2,b3,……,bm的位置进行互换
变为(b1,b2,b3,……,bm,a1,a2,a3,……,am)
// 顺序表类型定义
typedef struct SqList{
ElemType *data;
int length,MaxSize;
}SpList;
/*算法思想: 进行三次逆置, (a1,a2,a3,……,am,b1,b2,b3,……,bm)
首先将前 m (a1,a2,a3,……am)个元素逆置 (am ,……,a3,a2,a1,b1,b2,b3,……,bm)
然后将后 n(b1,b2,b3,……,bn) 个元素逆置 (am ,……,a3,a2,a1,bm,……,b3,b2,b1)
最后将m+n (整体)在进行一次逆置 (b1,b2,b3,……,bm,a1,a2,a3,……,am)
*/
// 逆置
void Reverse(SqList &A,int begin,int end){
ElemType temp;
for(int i = 0;i<end-begin+1/2;i++){
temp = A.data[begin];
A.data[begin] = A.data[end-i];
A.data[end-i] = temp;
}
}
//
void Exchange(SqList A,int m,int n){
Reverse(A,0,m-1);
Reverse(A,m,m+n-1);
Reverse(A,0,m+n-1);
}
8、2010年408统考真题 (X0,X1,X2,X3,…Xp-1,Xp,Xp+1 …,Xn-1) 变为 (Xp,Xp+1,……Xn-1,X0,X1,X2……Xp-2,Xp-1)
// 顺序表类型定义
typedef struct SqList{
ElemType *data;
int length,MaxSize;
}SpList;
/*算法思想: 进行三次逆置, (X0,X1,X2,X3,…Xp-1,Xp,Xp+1 …,Xn-1)
首先将前 p-1个元素逆置 (Xp-1,Xp-2,……,X2,X1,X0,Xp,Xp+1 …,Xn-1)
然后将后 p~n个元素逆置 (Xp-1,……,X2,X1,X0,Xn-1,Xn-2,…,Xp+1,Xp)
最后将 n (整体)在进行一次逆置 (Xp,Xp+1,……Xn-1,X0,X1,X2……Xp-2,Xp-1)
*/
// 逆置
void Reverse(SqList &A,int begin,int end){
ElemType temp;
for(int i = 0;i<end-begin+1/2;i++){
temp = A.data[begin];
A.data[begin] = A.data[end-i];
A.data[end-i] = temp;
}
}
//
void Exchange(SqList A,int m,int n){
Reverse(A,0,p-1);
Reverse(A,p,n-1);
Reverse(A,0,n-1);
}
二、链表
1、链表有关的删除操作
1、在带头结点的单链表L中,删除所有值为 x 的结点
// 单链表的定义
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*算法思想:p结点从头到尾扫描单链表,pre指向*p的前驱结点,*q指向值为x的结点,*/
void Delete_X(LinkList &L,ElemType x){
LNode *p,*q,*pre; // q 表示待删除结点
p = L->next;
pre = L;
while(p!=NULL){
if(p->data == x){
//pre->next = p->next
//free(p);
//p = pre->next;
q = p;
p = p->next;
pre->next = p;
free(q);
}else{
pre = p;
p = p->next;
}
}
}
2、在带头结点得单链表L中,删除最小值得结点
// 单链表的定义
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*
算法思想:首先遍历整个链表找到最小值结点,然后进行删除,
指针p用来遍历整个链表,pre指向p的前驱,
minp指向最小值结点,minpre指向最小值结点的前驱
扫描过程中,如果 p->data < minp->data ,将 pre 和 p的值赋值给 minpre 和 minp
扫描完毕,minp指向最小值结点,minpre 指向最小值结点的前驱
*/
LinkList Delete_min(LinkList &L){
LNode *pre = L;
LNode *p = pre->next;
LNode *minp = p;
LNode *minpre = pre;
while(p!=NULL){
if(p->data < minp->data){ // 找到比之前小的结点
minp = p;
minpre = pre;
}
pre = p; // 继续扫描下一个结点
p = p->next;
}
minpre->next = minp->next; // 删除最小值结点
free(minp);
return L;
}
3、在带头结点的无序单链表L中,删除表中值介于m和n之间(m<n)的值
// 单链表的定义
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*算法思想:遍历整个链表,找到符合条件的结点,进行删除*/
void Delete_Range(LinkList &L,int min,int max){
LNode *pre = L;
LNode *p = L->next;
while(p!=NULL){
if(p->data > min && p->data<max){
pre->next = p->next; // 删除指定结点
free(p);
p = pre->next;
}else{ // 寻找下一个结点
pre = p;
p = p->next;
}
}
}
4、在一个递增有序的单链表中,删除重复的元素
// 单链表的定义
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*算法思想:因为是有序表,所以重复的元素是相邻的*/
viod Delete_Same(LinkList &L){
LNode *pre = L->next;
LNode *p = pre->next;
while(p!=NULL){
if(pre->data == p->data){ // 找到重复结点
pre->next = p->next; // 释放相同元素结点
free(p);
p = pre->next
}else{
pre = p;
p = p->next;
}
}
}
5、【2015年408真题】单链表A中,对于绝对值相等的结点,仅保留第一次出现的结点,而删除其余绝对值相等的结点
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*算法思想:用空间换时间,申请一个大小为 N+1的辅助空间(初始为0),第一次出现保留(将标记从0变为1),否则删掉结点 */
void fun(LinkList &L,int n){
LNode *p = L->next;
LNode *pre;
int m;
int *q = (int *)malloc(sizeof(int)*(n+1)); // 开辟辅助空间
for(int i = 0;i<n+1;i++){ // 辅助空间初始化
*(q+i) = 0;
}
while(p!=NULL){
m = p->data>0?p->data:-p->data;
if(*(q+m) == 0){ // 判断该节点是否出现过
*(q+m) ==1; // 首次出现
p = p->next; // 保留
}
else{
pre->next = p->next;
free(p);
}
}
}
2、寻找公共结点
1、给定两个单链表,找出两个链表的公共结点
// 方法一 :双循环,时间复杂度高
// 单链表的定义
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*算法思想:暴力解法 ,通过循环,指针p用于遍历A链表,指针q用于遍历B链表,
p先指向第一个结点,然后遍历B链表,让B中的每一个节点和p比较,找到相同结点则直接返回,
如果没有找到,p指向下一个结点,q返回第一个结点,知道p指向空循环结束
*/
LinkList Search_common(LinkList A,LinkList B){
LNode *p = A->next;
LNode *q = B->next;
while(p!=NULL){
while(q!=NULL){
if(p == q){ // 找到公共结点
return p; // 将公共节点返回
}else{
q = q->next; //
}
}
// 一轮循环没有找到相同结点
p = p->next;
q = q->next;
}
}
// 方法二:是否同时到达表尾
/*算法思想:让两条链表同时到达表尾,如果有公共结点,那么p,q可以同时到达表尾,没有公共结点的话,p,q不能同时到达表尾
如果A,B链表等长,那么就同时向后移动,如果A,B链表不等长,那么就先让长的链表先移动K个单位,两条链表等长以后再同时向后移动*/
// 单链表的定义
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*求表长*/
int ListLen(LinkList L){
LNode *p = L->next;
int len = 0;
while(p!=NULL){
len++;
p = p->next;
}
return len;
}
LinkList Search_common(LinkList A,LinkList B){
LNode *p; // 指向更长的链表
LNode *q; // 指向更短的链表
int k;
int lenA = ListLen(A);
int lenB = ListLen(B);
if(lenA>lenB){
k = lenA-lenB; // 求出两个链表长度差
p = A->next;
q = B->next;
}else{
k = lenB-lenA; // 求出两个链表长度差
p = B->next;
q = A->next;
}
while(k--){
p = p->next; // 长的链表先向前移动k位,然后两条链表同时移动
}
while(p!=NULL){
if(p == q){ // 找到公共结点
return p;
}else{ // 没有找到公共结点,p , q同时向后移动
p = p->next;
q = q->next;
}
}
return NULL;
}
2、【2012年真题】假定采用带头结点的单链表保存单词,当两个单词有相同的后缀时,可以共享相同的后缀空间,例如 loading, being,请设置算法找到两个链表共同后缀的起始地址
// 单链表的定义
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*求表长*/
int ListLen(LinkList L){
LNode *p = L->next;
int len = 0;
while(p!=NULL){
len++;
p = p->next;
}
return len;
}
LinkList Search_common(LinkList A,LinkList B){
LNode *p; // 指向更长的链表
LNode *q; // 指向更短的链表
int lenA = ListLen(A);
int lenB = ListLen(B);
for(p = A->next;lenA>lenB;lenA--){ // A更长,p向后移
p = p->next;
}
for(q = B->next;lenB>lenA;lenB--){ // B更长,q向后移
q = q->next;
}
while(p!=NULL&&p!=q){ // 没有公共后缀
p = p->next;
q = q->next;
}
if(p==NULL){
return NULL;
} else{
return p;
}
}
}
3、【2009年真题】寻找倒数第k个结点 双指针,间隔一定,同步后移
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*算法思想:先将p移动到第k个位置,p,q一起后移,直到p指到表尾结点,则q指向倒数第k个结点 */
int Search_K(LinkList L,int k){
int count = 0;
LNode *p = L->next,*q = L->next;
while(p!=NULL){
if(count<k){
count++; // 计数, 如果count<k 则只移动p;
}else{
q = q->next; // 之后让p,q同时移动
}
p = p->next;
}
if(count<k){
return 0;
}else{
printf("%d",q->data);
return 1;
}
}
3、头插法和尾插法应用
1、头插法建立单链表(一般用于链表的逆置
)头插防断链 就是说用头插法时要给 p指针一个后继结点
// 单链表的定义
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*头插法建立单链表*/
LinkList Insert_Head(LinkList &L){
LNode *s;
int x;
L = (LinkList)malloc(sizeof(LNode)); // 创建头结点
L->next = NULL; // 初始为空链表
scanf("%d",&x);
while(x!=-1){
s = (LNode *)malloc(sizeof(LNode)); // 创建新结点
s->data = x;
s->next = L->next; // 将新结点插入表头
L->next = s;
scanf("%d",&x);
}
return L;
}
、2、尾插法建立单链表 尾插留尾指针 用尾插法时要有一个尾指针 r
// 单链表的定义
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*尾插法建立单链表*/
LinkList Insert_Head(LinkList &L){
LNode *s;
LNode *r; // 表尾指针
int x;
L = (LinkList)malloc(sizeof(LNode)); // 创建头结点
r = L;
scanf("%d",&x);
while(x!=-1){
s = (LNode *)malloc(sizeof(LNode)); // 创建新结点
s->data = x;
r->next = s;
r = s; // r 指向新的表尾结点
scanf("%d",&x);
}
r->next = NULL; // 尾结点指针指向空
return L;
}
1、单链表逆置
1、带头结点的单链表就地逆置 头插法
// 单链表的定义
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*算法思想:用头插法*/
LinkList Reverse(LinkList L){
LNode *p = L->next;
LNode *r; // P 的后继结点
while(P->NULL){
r = p->next; // 保留p的后继,防止断链
p->next = L->next; // 头插法
L->next = p;
p = r;
}
return L;
}
2、【2019年真题】L={a1,a2,a3,……an}------>L={a1,an,a2,an-1,a3,an-2……}
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*算法思想:
找中间结点:两个指针同步从开头遍历,一个慢指针一次走一步,一个快指针一次走两步,当快指针到达表尾时,慢指针就刚好指向中间结点
后半段逆置:头插法
合并 :尾插法
*/
void change_list(LinkList &L){
LNode *p,*q,*r,*s;
// 1、寻找中间结点
while(q->next!=NULL){
p = p->next; // p走一步
q = q->next; // q走两步
if(q->nextQ=NULL){
q = q->next;
}
}
// 2、逆置(头插法)
q = p->next; // 后半段链表,p为中间结点,q为后半段链表的首结点
while(q!=NULL){
r = q->next; // 头插法,防止断链
q->next = p->next;
p->next = q;
q = r;
}
// 3、从新合并
s = L->next; // s指向前半段第一个结点,即插入点
q = p->next; // q 指向后半段第一个结点
p->next = NULL;
while(q!=NULL){
r = q->next;
q->next = s->next;
s->next = q;
s = q->next; // s指向前半段下一个插入点
q = r;
}
}
2、链表归并与分解
1、将一个带头结点的单链表A分解为两个带头结点的单链表A和B,使得A表中保存序号是奇数的元素,B中保存序号是偶数的元素
// 单链表的定义
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*算法思想:不断的使用尾插法,序号奇数插入A,偶数插入B*/
LinkList Creat(LinkList &A){
LNode *p = A->next;
LinkList B = (LinkList)malloc(sizeof(LNode)); // 创建B链表
B->next = NULL; // B链表初始化
A->next = NULL; // 置空新的A链表
LNode *ra=A,*rb = B; // 两个尾指针
int i = 0; // 记录序号是奇数还是偶数
while(p!=NULL){
i++;
if(i%2 == 0){ // 偶数位插入B
rb->next = p; // 尾插法
rb = p;
}else{ // 奇数插入A
ra->next = p;
ra = p;
}
p = p->next;
}
ra->next = NULL; // 表尾指针指空
rb->next = NULL;
return B;
}
2、A={a1,b2,a2,b2……an,bn},采用带头结点的单链表存放,将其拆分为两个单链表A={a1,a2,……an},B={bn,bn-1,……b2,b1}
// 单链表的定义
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*算法思想:遍历A链表,将奇数位尾插入A中,偶数位头插入B中*/
LinkList Creat(LinkList &A){
int i = 0;
LNode *p = A->next,*q;
LNode *ra = A;
LinkList B = (LinkList)malloc(sizeof(LNode));
B->next = NULL;
A->next = NULL;
while(p!=NULL){
i++;
if(i%2 == 0){ // 偶数位,头插入B
q = p->next; // 头插法遍历原来的A链表时,保留p的后继结点,防止断链
p->next = B->next;
B->next = p;
p = q;
}else{ // 奇数位,尾插入A中
ra->next = p; // 尾插法
ra = p;
p = p->next;
}
}
ra->next = NULL;
return B;
}
3、将两个按元素值递增排序的单链表合并位一个按元素值递减排序的单链表
// 单链表的定义
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*算法思想:依次比较A和B中的值,将小的头插入到C中,如果其中一条链表有元素剩余,则依次进行头插入C中*/
void MergeList(LinkList &A,LinkList &B){
LNode *p = A->next;
LNode *q = B->next;
LNode *t; // 防止断链
A->next = NULL // A置空
while(p!=NULL&&q!=NULL){
if(p->data<=q->data){ // 将较小的头插入A中
t = p->next; //头插法遍历原来的链表时,保留p的后继结点,防止断链
p->next = A->next;
A->next = p;
p = t;
}else{ // 将较小的B头插入A中
t = q->next;
q->next = A->next;
A->next = q;
q = t;
}
}
while(p!=NULL){ // A中还有元素剩余,依次头插入A中
t = p->next; //头插法遍历原来的链表时,保留p的后继结点,防止断链
p->next = A->next;
A->next = p;
p = q;
}
while(q!=NULL){ // B中还有元素剩余,依次头插入A中
t = q->next;
q->next = A->next;
A->next = q;
q = t;
}
free(B);
}
4、A,B为元素递增有序的单链表,找到A和B中的公共元素,存放到C中
// 单链表的定义
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*算法思想:遍历A和B链表,比较元素值,将元素值小的指针后移,将相等的元素值尾插法插入到C中*/
void Creat_Conmmon(LinkList A,LinkList B){
LinkList C = (LinkList)malloc(sizeof(LNode)); // 创建C链表
C->next = NULL; // 初始化C链表
LNode *p = A->next;
LNode *q = B->next;
LNode *r = C;
LNode *s;
while(p!=NULL&&q!=NULL){
if(p->data > q->data){ //更小的指针后移, q向后移
q = q->next;
}else if(p->data < q->data){ // p向后移
p = p->next;
}else{ // 相同结点尾插法插入C中
s = (LNode *)malloc(sizeof(LNode));
s->data = p->data;
r->next = s;
r = s;
// p,q同时后移
p = p->next;
q = q->next;
}
}
r->next = NULL;
}
5、A,B两个单链表递增有序,求A,B的交集并存放于A中
// 单链表的定义
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*算法思想:依次扫描A,B两条链表,比较data域的值,将较小的指针向后移动(并释放空间),若
两者相等,则尾插入A中,直到遍历表尾,(若A链表还有元素剩余,则逐个释放剩余元素,只保留公共元素)*/
void Union(LinkList &A,LinkList &B){
LNode *p = A->next;
LNode *q = B->next;
LNode *u;
A->next = NULL; // A链表置空,重新插入元素
LNode *r = A;
while(p!=NULL && q->next!=NULL){
if(p->data < q->data){ // 元素小的指针后移,并释放空间
u = p;
p = p->next;
free(u);
}
else if(p->data > q->data){
u = q;
q = q->next;
free(u);
}
else{ // 找到公共元素,保留一个,释放一个
r->next = p;
r = p; // 保留p释放q;
p = p->next;
u = q;
q = q->next;
free(u);
}
}
while(p!=NULL){ // A链表还存在元素,但是已经一定不含公共结点,依次释放空间
u = p;
p = p->next;
free(u);
}
while(q!=NULL){ // B链表还有元素
u = q;
q = q->next;
free(u);
}
r->next = NULL;
free(B);
}
4、寻找相同子序列
1、两个整数子序列A = a1,a2……an B= b1,b2,……bn,存放到两个单链表中,判断序列B是否为A的连续子序列
// 单链表的定义
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*算法思想:暴力法:类似字符串的模式匹配,依次遍历A和B链表,如果data值相同,同时后移,如果不相同
A返回开始比较结点的后继结点,B则从头开始
*/
bool Pattern(LinkList A,LinkList B){
LNode *p = A->next;
LNode *q = B->next;
LNode *pre = p;
while(p!=NULL&&q!=NULL){
if(p->data == q->data){ // 结点值相同,两个结点同时向后移
p = p->next;
q = q->next;
}else{
pre = pre->next; //
p = pre; // A返回开始比较结点的后继结点
q = B->next; // B则从头开始
}
}
if(q == NULL){ // B中没有元素了,说明B是A的自序列
return true;
}else{
return false;
}
}
5、循环链表
1、判断带头结点的循环双链表是否对称 (元素值)
// 双链表的定义
typedef struct DNode{
ElemType data;
struct DNode *prior,*next;
}DNode,*DLinkList;
/*算法思想:让p结点从左往右移动,q结点从右往左移动,直到他们指向同一个结点
当循环双链表中结点个数为奇数个时(p=q),当结点为偶数个时(p->next = q,q->prior = p)
*/
int Symmetry(DLinkList &A){
DNode *p = A->next,*q = A->prior;
while(p!=q && q->prior = p){
if(p->data == q->data){ // 元素值相同,指针同时移动
p = p->next;
q = q->prior;
}
else{ // 只要有一个元素不相等就不对称
return 0;
}
}
return 1;
}
2、有两个循环单链表,头指针分别为 h1,h2,将其合并
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*算法思想:找到h1的表尾结点p,找到h2的表尾结点q,将p指向h2,q指向h1,构成一整条循环单链表*/
LinkList Link(LinkList &h1,LinkList &h2){
LNode *p,*q;
p = h1;
q = h2;
while(p->next!=NULL){ // 寻找h1的表尾结点
p = p->next;
}
while(q->next!=NULL){ // 寻找h2的表尾结点
q = q->next;
}
p->next = h2;
q->next = h1;
return h1;
}
3、反复找出循环单链表中结点值最小的结点并输出,然后将结点删除,直到链表为空,再删除表头结点
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*算法思想:反复找出当前的最小值结点,并删除,直到链表为空,释放头结点L*/
void Del_all(LinkList &L){
LNode *p,*pre,*minp,*minpre;
while(L->next!=L){
p = L->next;
pre = L;
minp = p;
minpre = pre;
while(p!=L){
if(p->data < minp->data){ // 找最小值结点
minp = p;
minpre = pre;
}
pre = p;
p = p->next;
}
printf("%d",minp->data);
minpre->next = minp->next;
free(minp);
}
free(L);
}