1、利用结点右孩子指针将一棵二叉树的叶子结点按照从左往右的顺序串成一个单链表(head初值为NULL,定义两个指针head和tail分别指向第一个叶子结点和最后一个叶子结点)?
void link(BTNode *p, BTNode *&head, BTNode *&tail)
{
if(p != NULL)
{
if(p-lchild==NULL && p->rchild==NULL)
{
if(head==NULL) //head刚开始为空,所以让其指向第一个叶子结点
{
head = p;
tail = p;
}else{
tail->rchild = p;
tail = p;
}
}
link(p->lchild,head,tail);
link(p->rchild,head,tail);
}
}
思想:
2、有一个二叉树,其结点的关键字是整数,利用叶子结点的右指针将所有的关键字是偶数的叶子结点链接到一个新的单链表中去?
void link(BTNode *p, BTNode *&head)
{
BTNode *q; //让此指针用来链接叶子结点
if(p != NULL)
{
if(p->lchild==NULL && p->rchild==NULL)
{
while(p->data % 2 == 0)
{
if(head==NULL)
{
head = p;
q =p;
}else{
q->rchild = p;
q = p;
}
}
}
link(p->lchild,head);
link(p->rchild,head);
}
}
思想:
3、增加一个指向双亲结点的指针parent,设计一个算法,给这个指针赋值,并输出所有结点到根节点的路径?
(1)修改结构体:
typedef struct BTNode
{
char data;
struct BTNode *parent;
struct BTNode *lchild;
struct BTNode *rchild;
}BTNode;
(2)给parent指针赋值
void triBTree(BTNode *p, BTNode *q)
{
if(p != NULL)
{
p->parent = q; //根节点时q为NULL
q = p;
triBTree(p->lchild,q);
triBTree(p->rchild,q);
}
}
(3)打印路径(打印单个结点到根节点的路径)
void printPath(BTNode *p)
{
while(p != NULL)
{
printf("%d",p->data);
p = p->parent;
}
}
(4)(打印所有结点到根节点的路径)
void printAllPath(BTNode *P)
{
if(p != NULL)
{
printPath(p); //调用(3)打印单个结点的函数
printAllPath(p->lchild);
printAllPath(p->rchild);
}
}
4、设计一个算法。输出从根节点到每个叶子结点的路径。
int i;
int top = 0;
char pathStack[maxSize];
void allPath(BTNode *p)
{
if(p != NULL)
{
pathStack[top] = p->data;
++top;
if(p->lchild==NULL && p->rchild==NULL)
{
for(i=0; i<top; ++i)
{
printf("%d",pathStack[i]);
}
}
allPath(p->lchild);
allPath(p->rchild);
--top;
}
}
5、设计一个算法,求二叉树中值为x的结点的层号。
int n=1; //确定层号变量
void getLeno(BTNode *p, char x)
{
if(p != NULL)
{
if(p->data == x)
printf("%d",n);
++n;
getLeno(p->lchild,x);
getLeno(p->rchild,x);
--n;
}
}
思想:
6、计算二叉树的高度(深度)
int getHigh(BTNode *p)
{
int LD,RD;
if(p == NULL)
return 0;
else{
LD = getHigh(p->lchild);
RD = getHigh(p->rchild);
return (LD > RD? LD:RD)+1;
}
}
7、查找二叉树中等于key值的结点是否存在(存在了用q指针指向,否则q=NULL)
void search(BTNode *p, BTNode *&q, int key)
{
if(p != NULL)
{
if(p->data == key)
q = p;
else{
search(p->lchild,q,key);
if(q == NULL) //剪枝操作,节省时间
search(p->rchild,q,key);
}
}
}
8、输出二叉树先序遍历第k个结点的值
int n=0;
void trave(BTNode *p, int k)
{
if(p != NULL)
{
++n;
if(n == k)
printf("%d",p->data)
return; //结束遍历
else{
trave(p->lchild,k);
trave(p->rchild,k);
}
}
}
9、将顺序表中元素逆置
void reverse(Sqlist &L)
{
int i,j;
int temp;
for(i=0,j=L.length-1; i<j; ++i,--j)
{
temp = L.data[j];
L.data[j] = L.data[i];
L.data[i] = temp;
}
}
10、从一给定的顺序表L中删除下标i~j(i<=j,包括i,j)的所有元素,假定i,j都是合法的。
void delet(Sqlist &L, int i, int j)
{
int leno;
int m;
leno = j-i+1; //删除元素的长度
for(m=j+1; m<L.length; ++m)
L.data[m-leno] = L.data[m];
L.length += leno;
}
11、已知一个带头节点的单链表head,假设结点中的元素为整数,试设计算法:按递增次序输出单链表中各个结点的数据元素,并释放结点所占存储空间。
void minDelete(LinkList head)
{
LinkList pre,p,q; //pre始终指向最小值得前驱,p是当前结点
while(head->next != NULL)
{
pre = head;
p = pre->next;
while(p->next != NULL)
{
if(p->next->data < pre->next->data)
pre = p;
p = p->next;
}
printf("%d",pre->next->data);
q = pre->next;
pre->next = q->next;
free(q);
}
free(head);
}
12、假设以带头结点的循环单链表表示队列,并且只设一个指针rear指向队尾结点,但不设头指针,请写出相应的入队列和出队列算法。
队列特点:先进先出,尾进头出
入队列算法:
void enQueue(LNode *&rear, int x) //元素x插入队列
{
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data = x;
s->next = rear->next;
rear->next = s;
rear = s;
}
出队列算法:
void deQueue(LNode *&rear, int &x) //对列元素出队,用x接收
{
LNode *s;
if(rear->next == rear)
retunr 0;
else{
s = rear->next->next; //指向开始结点
rear->next->next = s->next; //将开始结点删除
x = s->data;
if(s == rear) //删除的先后顺序问题,因为我们只设了一个尾指针,如果只剩尾指针和头指针的话,按上继续进行则,先删除尾指针,头结点将无法删除
rear = rear->next;
free(s);
return 1;
}
}
13、已知一个带头结点的单链表L,试编写算法:清空单链表。
清空不是销毁,只是清空结点的内存空间
Status clearList(LinkList L) //LinkList结构体名称
{
LinkList p,q; //定义两个指针,p用来遍历,q用来指向p
p = L->next;
while(p)
{
q = p->next;
free(p);
p = q;
}
L->next = NULL;
return OK;
}
14、将以带头结点的单链表head逆置。要求:逆置在原链表进行,不允许构造一个链表。
void Link_Reverse(LinkList &head)
{
LinkList p,q;
p = head->next;
head->next = NULL;
while(p)
{
q = p->next;
p->next = head->next; //头插法逆序
head->next = p;
p = q;
}
}
15、已知L1、L2分别为两个循环单链表(带头结点)的指针,m、n分别为L1、L2表中数据元素个数,试设计一个算法,用最快速度将两表合成一个带头结点的循环单链表?
LinkList Union(LinkList &L1,LinkList &L2, int m,int n)
{
if(m<0 || n<0)
{
printf("表长有错");
exit(0);
}
if(m<n)
{
if(m==0)
return L2;
else
{
p = L1;
while(p->next != L1)
{
p->next = L2->next;
L2->next = L1->next;
free(L1);
}
}
}else
{
if(n==0)
return L1;
else
{
p = L2;
while(p->next != L2)
{
p->next = L1->next;
L1->next = L2->next;
free(L2);
}
}
}
}
16、设计一个算法,判定带头结点的单链表L是否是递增的?
int IsAscending(LinkList L)
{
LinkList pre,p;
pre = L;
p = L->next;
while(p->next != NULL)
{
if(pre->next->data > p->next->data)
return 1; //表示非递增
pre = p;
p = p->next;
}
return 0; //表示递增
}
17、有一种排序算法叫做计数排序,这种排序算法对一个待排序的表(采用顺序存储)进行排序,并将排序结果存放到另一个新的表中。必须注意的是,表中所有待排序的关键字互不相同,计数排序算法针对表中的每个元素,扫描待排序的表一趟,统计表中有多少个元素的关键字比该关键字小,假设对某一个元素统计出数值count,那么这个元素在新的有序表中合适的存放位置即为count,写出该算法?
void countSort(int A[], int B[], int n)
{
int i,j count;
count = 0;
for(i=0;i<n;++i)
{
for(j=0;j<n;++j)
{
if(A[i] > A[j])
++count;
}
B[count] = A[i]; //i元素存放的位置就是B中count的位置
}
}
18、若二叉树采用二叉链表存储,设计一个算法,求指定结点p的父节点。
typedef struct BTNode
{
}
BTNode getParent(BTNode *T, BTNode p)
{
if(T == p)
return NULL;
if(T != NULL)
{
if(T->lchild == p || T->rchild==p)
e = T;
getParent(T->lchild,p,e);
getParent(T->rchild,p,e);
}
}
19、现有两个单链表A和B,其中的元素递增有序,在不破坏原链表的情况下,设计一个算法,求这两个链表的交集,并将结果存放在链表C中。
1、尾插法,交集中元素在C中同样是递增的
void interSection(LNode *A, LNode *B, LNode *&C)
{
LNode la,lb,lc;
la = A->next;
lb = B->next;
C = (LNode *)malloc(sizeof(LNode));
C->next = NULL;
lc = C;
while(la!=NULL && lb!=NULL)
{
if(la->data < lb->data)
la = la->next;
else if(la->data > lb->data)
lb = lb->next;
else
{
lc->next = la;
la = la->next;
lb = lb->next;
lc = lc->next;
}
}
lc->next = NULL;
}
2、头插法,交集中元素在C中是递减的
void interSection(LNode *A, LNode *B, LNode *&C)
{
LNode *la = A->next;
LNode *lb = B->next;
C = (LNode *)malloc(sizeof(LNode));
C->next = NULL;
while(la && lb)
{
if(la->data < lb->data)
la = la->next;
else if(lb->data < la->data)
lb = lb->next;
else
{
la->next = C->next;
C->next = la;
la = la->next;
lb = lb->next;
}
}
}
20、有一个顺序表L,第一趟对该序列的奇数进行排序,第二趟对该序列的偶数进行排序,如此反复进行,当有L.data[i]>L.data[i+1]发生交换?
void odd_evenSort(Sqlist L)
{
int i;
bool flag = false;
while(!flag)
{
flag = true;
for(i=1; i<L.length; i+=2) //第一趟对奇数进行排序
{
if(L.data[i] > L.data[i+1])
{
flag = false;
swap(L.data[i],L.data[i+1]);
}
}
for(i=0; i<L.length; i+=2) //第二趟对偶数进行排序
{
if(L.data[i] > L.data[i+1])
{
flag = false;
swap(L.data[i],L.data[i+1]);
}
}
}
}
void swap(int &a ,int &b)
{
int temp;
temp = a;
a = b;
b = temp;
}
21、将n个整数存放到数组R中,设计一个算法,将R中的序列循环左移p(0
例如:123456,循环左移3个元素
首先将123逆置成321
其次将456逆置成654
最后整体逆置变成456123(和循环左移的一样)
void Reverse(int R[],int left,int right)
{
int i,j,temp;
for(i=left,j=right; i<j; ++i,--j)
{
temp = R[i];
R[i] = R[j];
R[j] = temp;
}
}
void RCR(int R[],int n, int p)
{
if(p<0 || p>n)
printf("ERROR");
else
{
Reverse(R,0,p-1);
Reverse(R,p,n-1);
Reverse(R,0,n-1);
}
}
22、已知一个顺序表L,其中的元素递增有序排列,设计一个算法,插入一个元素x(x为int型),后保持该顺序表仍然递增有序(不考虑失败的情况)?
两个步骤(此解法是将两个步骤合一,也可以分开写)
查找
插入
void findAndInsert(Sqlist &L,int x)
{
int i,temp;
for(i=0; i<L.length; ++i)
{
if(x < L.data[i])
temp = i;
}
for(i=L.length-1; i>=temp; --i)
L.data[i+1] = L.data[i];
L.data[temp] = x;
++(L.length); //顺序表长度发生变化,记得表长一定要改变
}
23、设顺序表用数组A[]表示,表中元素存储在数组下标0~m+n-1的范围内,前m个元素递增有序,后n个元素也递增有序,设计个算法使整个顺序表有序。
首先分清楚范围问题
0~m-1是前m个元素
m~m+n-1是后n个元素
void Sort(int A[], int m, int n)
{
int i,j,temp;
for(i=m, i<m+n; ++i)
{
temp = A[i];
for(j=i-1; j>=0 && temp<A[j]; --j)
A[j+1] = A[j];
A[j+1] = temp;
}
}
思想:(这个算法图示比较好理解),将其看成两个顺序表的数组,前m个元素是一个数组R[o·m-1],后n个是一个数组B[m~n+m-1],将B中数组逐个与R中数组元素比较(用变量temp接收),当temp>A[j]的时候,元素就插入在j+1的位置。
24、设计一个算法,将顺序表中所有元素逆置
结构体定义:
typedef struct
{
int data[maxSize];
int length;
}Sqlist;
void ReverseSq(Sqlist &L)
{
int i,j,temp;
for(i=0,j=L.length-1; i<j; ++i,--j)
{
temp = L.data[i];
L.data[i] = L.data[j];
L.data[j] = temp;
}
}
25、有一个顺序表L,其元素数据类型为整型数据,设计一个算法,将L中所有小于表头元素的整数存放在前半部分,大于表头元素的存放在后半部分?
快速排序的思想
void move(Sqlist &L)
{
int i=0,j=L.length-1;
int temp;
temp = L.data[i];
while(i<j)
{
while(i<j && L.data[j]>temp)
--j;
if(i<j)
{
L.data[i] = L.data[j];
++i;
}
while(i<j && L.data[i]<temp)
++i;
if(i<j)
{
L.data[j] = L.data[i];
--j;
}
}
L.data[i] = temp;
}
26、有一个递增非空单链表,设计一个算法删除值域重复的结点?
void delete(LNode *L)
{
LNode *p,*q;
p = L->next;
while(p->next != NULL)
{
if(p->data == p->next->data)
{
q = p->next;
p->next = q->next;
free(q);
}else
{
p = p->next;
}
}
}
27、设计一个算法,删除单链表(带头结点)中的一个最小值结点?
void DeleteMinElem(LNode *L)
{
LNode *pre=L;
LNode *p = pre->next;
LNode *q;
while(p->next != NULL)
{
if(pre->next->data > p->next->data)
pre = p;
p = p->next;
}
q = pre->next;
pre->next = q->next;
free(q);
}
28、设计一个算法,将一个头结点为A的单链表(数据域为整数)分解成两个单链表A和B,使得A链表中只含数据域为奇数的结点,B链表中只含数据域为偶数的结点,且保持原来的相对顺序?
void split(LNode *A, LNode *&B)
{
LNode *la,*lb,s;
B = (LNode *)malloc(sizeof(LNode));
B->next -NULL;
la = A;
lb = B;
while(la->next != NULL)
{
if(la->next->data%2 == 0)
{
s = la->next;
la->next = s->next;
s->next = NULL;
lb->next = s;
lb = s;
}else{
la = la->next;
}
}
}
29、写一个函数,逆序打印单链表中的数据,L指向单链表开始结点?
void printLn(LNode *L)
{
if(L != NULL)
{
printLn(L->next);
printf("%d",L->data);
}
}
30、设有两个有序链表表示的集合A和B,设计一个算法,判断是否相等?
int equal(LNode *A, LNode *B)
{
LNode *la,*lb;
la = A->next;
lb = B->next;
while(la && lb)
{
if(la->data == lb->data)
{
la = la->next;
lb = lb->next;
}else
return 0; //表示不等
}
if(la || lb) //俩个其中任有一个不为空则不等
return 0;
else
return 1;
}
31、已知一个带有表头结点的单链表,结点结构为:假设该链表只给出头指针head,在不改变链表的前提下,查找链表中倒数第k个位置上的结点,若成功,输出该结点data值,并返回1,否则返回0。
int findElem(LNode *head)
{
LNode *pre,*p;
int i=1;
pre = head;
p = head->next;
while(p != NULL)
{
p = p->next;
++i;
if(i>k)
pre = pre->next;
}
if(pre == head)
return 0;
else{
printf("%d",pre->data);
return 1;
}
}
32、不带头结点的单链表存储链栈,设计初始化栈,判断栈是否为空,进栈和出栈等相应操作?
1、初始化栈
void initStack(LNode *&L)
{
L = NULL;
}
2、判断栈是否为空
int isEmpty(LNode *L)
{
if(L == NULL)
return 0;
else
return 1;
}
3、进栈
void push(LNode *&L,int x)
{
LNode *s;
s = (LNode *)malloc(sizeof(LNode));
s->next = NULL:
s->data = x;
s->next = L;
L = s;
}
4、出栈
int pop(LNode *&L,int &x)
{
LNode *p;
if(L==NULL)
return 0
p = L;
x = p->data
L = p->next;
free(p);
return 1;
}
栈:先进后出,采用头插法