初始设定
#include<iostream>
#include<cstdlib>
using namespace std;
typedef int ElemType;
typedef struct LNode{
ElemType data;
LNode *next;
}LNode,* LinkList;
int InitData[] = {1,2,3,4,5,6,7,8,9,10,11,12,13};
bool InitLinkList(LinkList &L){
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL;
LNode *p = L;
for(int i = 0;i < 10;i++){
LNode *s = (LNode*)malloc(sizeof(LNode));
s->data = InitData[i];
s->next = NULL;
p->next = s;
p = p->next;
}
return true;
}
bool InitLinkListNoHead(LinkList &L){
L = (LinkList)malloc(sizeof(LNode));
L->data = InitData[0];
L->next = NULL;
LNode *p = L;
for(int i = 1;i <= 9;i++){
LNode *q = (LNode*)malloc(sizeof(LNode));
q->next = p->next;
q->data = InitData[i];
p->next = q;
p = q;
}
return true;
}
01、设计递归算法,删除不带头结点的单链表L所有值为X的结点
思路
每一次判断结点所指的值是否要求删除,如果可以删除就指向下一个,将原来的点释放,不删除就指向下一个结点,递归调用算法,递归出口应该是传进null值即递归结束。
代码
void DeleteX(LinkList &L,ElemType e){
if(L == NULL)
return;
if(L->data == e){
LNode *p = L;
L = L->next;
free(p);
DeleteX(L,e);
}else{
DeleteX(L->next,e);//这一步开始写成了L=L->next; DeleteX(L,e);
//结果会导致断链
}
}
02、带头结点的单链表L,删除所有值为x的结点,并释放其空间。
思路
和第一题类似,但没有要求递归,所以用常规思路:记录要删除结点的前驱结点,以及工作指针指向待删除结点,工作指针要从第一个数据遍历到最后一个数据。
代码
void DeleteX(LinkList &L,ElemType e){
LNode *p = L->next;
LNode *priorP = L;
while(p != NULL){
if(p->data == e){
LNode *q = p;
priorP->next = p->next;
p = p->next;
free(q);
}else{
priorP = p;
p = p->next;
}
}
}
03、带头结点的单链表,反向输出
思路
把头结点作为一个空表,把后面的元素不断使用头插法,即将结点插入头结点的后面就可以实现单链表逆置。
代码
void ReverseLinkList(LinkList L){
LNode *p;
p = L->next;
L->next = NULL;
while(p != NULL){
LNode *q;
q = p;
p = p->next;
q->next = L->next;
L->next = q;
}
p = L->next;
cout<<endl;
while(p!=NULL){
cout<<p->data<<" ";
p = p->next;
}
cout<<endl;
}
04、带头结点的单链表,删除一个最小值的结点
思路
寻找最小值的前驱结点,所以用四个指针解决问题,工作指针p指针,工作指针p指针的前驱指针,指向最小值的指针,指向最小值前驱的指针。
代码
void DeleteMin(LinkList &L){
LNode *priorp = L,*p = L->next;
LNode *priorMin = priorp,*Min = p;
while(p!=NULL){
if(p->data < Min->data){
priorMin = priorp;
Min = p;
}
priorp = p;
p = p->next;
}
priorMin->next = Min->next;
free(Min);
}
05、带结点的单链表就地逆置
思路
把所有结点插到头结点的后面,即头插
代码
void ReverseLinkList(LinkList &L){
LNode *p = L->next;
L->next = NULL;
while(p != NULL){
LNode *q = p;
p = p->next;
q->next = L->next;
L->next = q;
}
}
06、带头结点的单链表使其递增有序
思路
默认单链表只有一个元素按照递增排,为接下来的每一个结点都找到他应该插入的前驱结点。即把无序表的每一个元素插入到有序表中合适的位置。
代码
void Sort(LinkList &L){
LNode *preP = L,*p = L->next;
L->next = NULL;
while(p != NULL){
LNode *prePos = L, *Pos = L->next;
while(Pos != NULL){
if(Pos->data > p->data){
break;
}
prePos = Pos;
Pos = Pos->next;
}
LNode * q = p;
preP = p;
p = p->next;
prePos->next = q;
q->next = Pos;
}
}
07带头结点的单链表(无序),删除介于两值之间的结点
思路
遍历所有的结点,记录符合要求的结点的前驱结点便于删除,用符合要求的结点设定工作指针,比较简单清楚。
代码
void DeleteRange(LinkList &L,ElemType Left,ElemType Right){
LNode *p = L->next;
LNode *prep = L;
while(p != NULL){
if(Left < p->data && p->data < Right){
LNode *q = p;
prep->next = p->next;
p = p->next;
free(q);
}else{
prep = p;
p = p->next;
}
}
}
08寻找两个单链表的公共结点
思路
公共结点表明,不但数据域相等,结点域也相等,了解这一点就明白了答案的思路,把两个单链表尾端对齐,多余的部分不看,当两个结点相等时,就找到了公共结点。(注意的是这道题返回公共结点如果用带头结点的输出函数会跳过一个点,debug弄了半天这)
代码
LinkList FindCommon(LinkList La,LinkList Lb){
int lengthla = 0,lengthlb = 0;
LNode *pa = La,*pb = Lb;
while(pa->next != NULL){
lengthla++;
pa = pa->next;
}
while(pb->next != NULL){
lengthlb++;
pb = pb->next;
}
LNode *Long,*Short;
int dist = 0;
if(lengthla>lengthlb){
Long = La->next;
Short = Lb->next;
dist = lengthla - lengthlb;
}else{
Short = La->next;
Long = Lb->next;
dist = lengthlb - lengthla;
}
while(dist--){
Long = Long->next;
}
while(Long != NULL){
if(Long->data == Short->data && Long->next == Short->next ){
return Long;
}
Long = Long->next;
Short = Short->next;
}
return NULL;
}
09带头结点的单链表,按递增次序输出所有值
思路
循环n趟,每次输出并删除最小值,常规思路,四个指针分别设定。
代码
void DeleteMin(LinkList &L){
LNode *prep = L,*p = L->next;
while(p != NULL){
LNode *preMin = L,*Min = L->next;
while(p!=NULL){
if(p->data < Min->data){
preMin = prep;
Min = p;
}
prep = p;
p = p->next;
}
preMin->next = Min->next;
cout<<Min->data<<" ";
free(Min);
Min = preMin->next;
prep = L;
p = L->next;
}
}
10带头结点A单链表分解为A,B两个单链表,使得A中为奇数序号元素,B中为偶数序号的元素
思路
把偶数个元素利用尾插法插到B结点后面,A中剩余元素只需要改后继next指针即可;我觉得更容易想到的思路是把A,B置空,直接将奇数序号元素和偶数序号元素分别尾插到A,B之后即可,这样虽然麻烦点但都是重复代码。
代码
LinkList Creat(LinkList &A){
LinkList B = (LinkList)malloc(sizeof(LNode));
LNode *rA = A,*rB = B;
LNode *p = A->next;
B->next = NULL;
A->next = NULL;
int count = 1;
while(p!=NULL){
LNode *q = p;
p = p->next;
if(count %2 == 1){
q->next = rA->next;
rA->next = q;
rA = q;
}else if(count %2 == 0){
q->next = rB->next;
rB->next = q;
rB = q;
}
count++;
}
return B;
}