一些算法真題選集,僅供參考,暫停更,開始手撕。
1. 統計出單鏈表HL中結點的值等於給定值X的結點數
int CountX(LNode *HL, ElementType X){
LNode *p;
int count = 0;
if(HL == NULL) return 0;
p = HL->next;
while(p != NULL){
if(p->data == X)
++count;
p = p->next;
}
return count;
}
2.設有一組初始記錄關鍵字序列(K1,K2,… Kn),要求設計一個算法能夠在 O(n) 的時間復雜度內將線性表划分成兩部分,其中左半部分的每個關鍵字均小於 Ki ,右半部分的每個關鍵字均大於等於 Ki
void quickpass(int r[], int s,int t)
{
int i=s, j=t, x=r[s];
while(i<j){
while (i<j &&r[j]>x) j=j-1; if (i<j) {r[i]=r[j];i=i+1;}
while (i<j && r[i]<x) i=i+1;if (i<j) {r[j]=r[i];j=j-1;}
}
r[i]=x;
}
3. 設有兩個集合A和集合B,要求設計生成集合C=A∩B的算法,其中集合A、B和C用鏈式存儲結構表示
typedef struct node
{ int data;
struct node *next;
}lklist;
void intersection(lklist*ha,lklist *hb,lklist *&hc)
{
lklist *p,*q,*t;
for(p=ha,hc=0;p!=0;p=p->next)
{
for(q=hb;q!=0;q=q->next)
{
if (q->data==p->data) break;
}
if(q!=0)
{
t=(lklist*)malloc(sizeof(lklist));
t->data=p->data;t->next=hc; hc=t;
}
}
}
4. 設計在單鏈表中刪除值相同的多余結點的算法
typedef int datatype;
typedef struct node
{
datatype data;
struct node *front, *next;
}lklist;
void delredundant(lklist *&head)
{
lklist *p,*q,*s;
for(p=head; p!=0; p=p->next)
{
for(q=p->next, s=q; q!=0;)
{
if(q->data==p->data)
{
s->next=q->next; free(q); q=s->next;
}else{
s=q; q=q->next;
}
}
}
}
5. 設計一個求結點 x 在二叉樹中的雙親結點算法
typedef struct node
{ datatype data;
struct node *lchild,*rchild;
} bitree;
bitree *q[20]; int r=0,f=0,flag=0;
void preorder(bitree *bt, char x)
{
if (bt!=0 && flag==0)
if (bt->data==x) { flag=1; return;}
else {
r=(r+1)% 20; q[r]=bt;
preorder(bt->lchild,x);
preorder(bt->rchild,x);
}
}
void parent(bitree *bt,char x)
{
int i;
preorder(bt,x);
for(i=f+1; i<=r; i++)
{
if (q[i]->lchild->data==x || q[i]->rchild->data) break;
}
if (flag==0) printf("not found x\n");
else if (i<=r) printf("%c",bt->data);
else printf("not parent");
}
6. 設單鏈表中有僅三類字符的數據元素(大寫字母、數字和其它字符),要求利用原單鏈表中結點空間設計出三個單鏈表的算法,使每個單鏈表只包含同類字符
typedef char datatype;
typedef struct node
{ datatype data;
struct node *next;
}lklist;
void split(lklist *head,lklist*&ha,lklist *&hb,lklist *&hc)
{
lklist *p; ha=0,hb=0,hc=0;
for(p=head;p!=0;p=head)
{
head=p->next; p->next=0;
if (p->data>='A' && p->data<='Z') {p->next=ha;ha=p;}
else if (p->data>='0' && p->data<='9')
{p->next=hb; hb=p;} else {p->next=hc; hc=p;}
}
}
7. 設計在鏈式存儲結構上交換二叉樹中所有結點左右子樹的算法
typedef struct node
{ int data;
struct node *lchild,*rchild;
}Bitree;
void swapbitree(Bitree *bt)
{
Bitree *p;
if(bt==0)
{
return;
}
swapbitree(bt->lchild);
swapbitree(bt->rchild);
p=bt->lchild;
bt->lchild=bt->rchild;
bt->rchild=p;
}
8. 在鏈式存儲結構上建立一顆二叉排序樹
#define n10
typedef struct node
{ int key;
struct node *lchild,*rchild;
}bitree;
void bstinsert(bitree *&bt,int key)
{
if (bt==0)
{
bt=(bitree*)malloc(sizeof(bitree));
bt->key=key;bt->lchild=bt->rchild=0;
}
else if (bt->key>key)
bstinsert(bt->lchild,key);
else bstinsert(bt->rchild,key);
}
void createbsttree(bitree *&bt)
{
int i;
for(i=1;i<=n;i++)bstinsert(bt,random(100));
}
9. 設計判斷兩個二叉樹是否相同的算法
typedef struct node
{ datatype data;
struct node *lchild, *rchild;
}bitree; //二叉鏈表存儲結構
int judgebitree(bitree *bt1,bitree *bt2)//判斷兩個二叉樹是否相同。
{
if (bt1==0 && bt2==0)//兩棵樹對應位置都為空返回1
return 1;
else if (bt1==0 || bt2==0 ||bt1->data!=bt2->data)
//兩棵樹的當前節點只有一個為空或者兩棵樹的當前節點的值不同。
return 0;
else
return judgebitree(bt1->lchild,bt2->lchild)*judgebitree(bt1->rchild,bt2->rchild);
}
10. 設計兩個有序單鏈表的合並排序算法
Typedef struct Lnode{
Datatype data;
Struct Lnode *next;
}Lnode,*linklist;
void Merge_List(Linklist &la,linklist &b){
LNode *pa=la->next,*pb=lb->next,*r; //r指針防止斷鏈
la->next=null;
while(pa&&pb){
if(pa->data >= pb->data){
r=pa->next;
pa->next=la->next;
la->next=pa;
pa=r; //pa重新指向未排序位置
}
if(pa->data <= pb->data){
r=pb->next;
pb->next=la->next;
la->next=pb;
pb=r;
}
}
if(pa) pb=pa;
while(pb){
r=pb->next;
pb->next=la->next;
la->next=pb;
pb=r;
}
free(lb); //釋放掉lb的空閑空間
}
11. 設計在順序有序表中實現二分(折半)查找的算法
struct record
{ int key;
int others;
};
int bisearch(struct record r[], int k)
{
int low=0, mid, high=n-1;
while(low<=high)
{
mid=(low+high)/2;
if(r[mid].key==k)
{
return (mid+1);
}
else if(r[mid].key>k)
{
high=mid-1;
}else{
low=mid+1;
}
}
return 0;
}
12. 設計判斷二叉樹是否為二叉排序樹的算法
//遞歸方式
KeyType predt=-32767;
int JudgeBST(BisTree bt)
{
int b1, b2;
if(bt==NULL)
{
return 1;
}else{
b1=JudgeBST(bt->lchild); //遞歸
if(b1==0 || predt>=bt->data)
return 0;
predt=bt->data;
b2=JudgeBST(bt->rchild);
return b2;
}
}
//非遞歸方式
int InOrderTraverse(BiTree T)
{
BiTree p;
p=T;
while(p||!StackEmpty(S))
{
if(p)
{
Push(S,p);
if(p->data>p->lchild->data)
p=p->lchild;
else return 0;
}
else
{
Pop(S,p);
cout<<p->data<<" ";
if(p->data<p->rchild->data)
p=p->rchild;
else return 0;
}
}
return 1;
}
13. 在鏈式存儲結構上設計直接插入排序
void straightinsertsort(lklist *&head)
{
lklist *s,*p,*q;
int t;
if(head==0 || head->next==0) return ;
else for(q=head, p=head->next; p!=0; p=q->next)
{
for(s=head; s!=q->next; s=s->next)
{
if(s->data > p->data) break;
if(s==q->next) q=p;
else{
q->next=p->next;
p->next=s->next;
s->next=p;
t=p->data;
p->data=s->data;
s->data=t;
}
}
}
}
14. 設計在鏈式結構上實現簡單選擇排序
typedef struct LNode
{ int data;
struct LNode *next
}*Linklist;
void simpleselectSort(Linklist *&head)
{
Linklist *p,*q,*s;
int min,t;
if(head==0 || head->next==0)
{
return;
}
for(q=head;q!=0;q=q->next)
{
min=q->data;
s=q;
for(p=q->next;p!=0;p=p->next)
{
if(min>p->data)
{
min=p->data;
s=p;
}
}
if(s!=q)
{
t=s->data;
s->data=q->data;
q->data=t;
}
}
}
15.設計求結點在二叉排序樹中層次的算法
int lev=0;
typedef struct node
{
int key;
struct node *lchild,*rchild;
}bitree;
void level(bitree *bt, int x)
{
if(bt!=0)
{
lev++;
if(bt->key==x)
{
return;
}
else if(bt->key>x)
{
level(bt->lchild, x);
}
}
else{
level(bt->rchild, x);
}
}
16. 設計一個在鏈式存儲結構上統計二叉樹中結點個數的算法
void countnode(bitree *bt,int &count)
{
if(bt!=0)
{
count++;
countnode(bt->lchild,count);
countnode(bt->rchild,count);
}
}
17. 設計一個算法將無向圖的鄰接矩陣轉為對應鄰接表的算法
typedef struct
{ int vertex[m];
int edge[m][m];
}gadjmatrix;
typedef structnode1
{ int info;
int adjvertex;
struct node1 *nextarc;
}glinklistnode;
typedef structnode2
{ int vertexinfo;
glinklistnode *firstarc;
}glinkheadnode;
void adjmatrixtoadjlist(gadjmatrix g1[ ],glinkheadnode g2[ ])
{
int i,j;glinklistnode *p;
for(i=0;i<=n-1;i++)g2[i].firstarc=0;
for(i=0;i<=n-1;i++)for(j=0;j<=n-1;j++)
if(g1.edge[i][j]==1)
{
p=(glinklistnode*)malloc(sizeof(glinklistnode)); p->adjvertex=j;
p->nextarc=g[i].firstarc; g[i].firstarc=p;
p=(glinklistnode*)malloc(sizeof(glinklistnode)); p->adjvertex=i;
p->nextarc=g[j].firstarc; g[j].firstarc=p;
}
}
18. 設計計算二叉樹中所有結點值之和的算法
void sum(bitree *bt,int &s)
{
if(bt!=0)
{
s=s+bt->data;
sum(bt->lchild,s);
sum(bt->rchild,s);
}
}
19. 設計將所有奇數移到所有偶數之前的算法
void quickpass(int r[], int s, int t)
{
int i=s,j=t,x=r[s];
while(i<j)
{
while (i<j && r[j]%2==0)
j=j-1;
if (i<j) {r[i]=r[j];i=i+1;}
while (i<j && r[i]%2==1)
i=i+1;
if (i<j) {r[j]=r[i];j=j-1;}
}
r[i]=x;
}
20. 設計判斷單鏈表中元素是否是遞增的算法
int isriselk(lklist *head)
{
if(head==0||head->next==0)return(1);
else
for(q=head,p=head->next;p!=0; q=p,p=p->next)
if(q->data>p->data) return(0);
return(1);
}
21. 設計在鏈式存儲結構上合並排序的算法
void mergelklist(lklist *ha,lklist *hb,lklist *&hc)
{
lklist *s=hc=0;
while(ha!=0 && hb!=0)
if(ha->data<hb->data)
{
if(s==0) hc=s=ha;
else {s->next=ha; s=ha;};
ha=ha->next;
}
else {
if(s==0) hc=s=hb;
else {s->next=hb; s=hb;};
hb=hb->next;
}
if(ha==0) s->next=hb;
else s->next=ha;
}
22. 設計在二叉排序樹上查找結點X的算法
bitree *bstsearch1(bitree *t, int key)
{
bitree *p=t;
while(p!=0)
if (p->key==key)return(p);
else if (p->key>key) p=p->lchild;
else p=p->rchild;
return(0);
}
23. 設關鍵字序列(k1,k2,…,kn-1)是堆,設計算法將關鍵字序列(k1,k2,…,kn-1,x)調整為堆
void adjustheap(int r[ ],int n)
{
int j=n,i=j/2,temp=r[j-1];
while (i>=1)
if(temp>=r[i-1])break;
else{
r[j-1]=r[i-1]; j=i; i=i/2;
}
r[j-1]=temp;
}
24.已知深度為h的二叉樹以一維數組BT(1:2h-1)作為其存儲結構。請寫一個算法,求該二叉樹中葉子結點的個數
int leaves(int h) //求深度為h以順序結構存儲的二叉樹的葉子結點
{
int BT[]; int len=2^h-1,count=0;
for(int i=1;i<=len;i++)
{
if(BT[i]!=0) //假定二叉樹結點值是整數,“虛結點”用0補充
{
if((i*2)>len) count++; //第i個結點沒有子女肯定是葉子結點
else if(BT[2*i]==0&&2*i+1<=len&&BT[2*i+1]==0) count++; //無左右子女結點為葉子
}
}
return count;
}
25、建立二叉樹
typedef struct node
{
int data;
struct node *lchild;
struct ndoe *rchild;
}btree;
void createbitree(bitree *&bt)
{
scanf("%c",&ch);
if(ch=='#')
bt=0;
else
{
bt=(bitree*)malloc(sizeof(bitree));
bt->data=ch;
createbitree(bt->lchild);
createbitree(bt->rchild);
}
}
26、利用尾部插入的方法建立單鏈表
typedef struct node
{
int data;
struct node *next;
}lklist;
void lklistcreate(lklist *&head)
{
for(i=1;i<=n;i++)
{
p=(lklist*)malloc(sizeof(lklist));scanf("%d",&(p->data));p->next=0;
if(i==1) head=q=p; else{q->next=p;q=p;}
}
}
27、n個元素采用順序存儲,設計直接插入排序算法
void insertsort()
{
//a為順序存儲所需數組,n為元素個數
for(int i=1;i<n;i++)
{
int key=a[i];
int j=i-1;
while(j>=0&&a[j]>key)
{
a[j+1]=a[j];
j--;
}
a[j+1]=key;
}
}
28、對含有n個互不相同元素的線性表,設計一個算法同時找最大元素和最小元素
void getMaxandMin(int A[],int n,int &max,int &min) //O(n)
{
int i;
max=min=A[0];
for(i=0;i<n;i++)
{
if(A[i]>max) max=A[i];
if(A[i]<min) min=A[i];
}
}
29、編寫一個算法,完成對n叉樹各節點的層次遍歷
// 定義n叉樹的節點結構體
typedef struct node_t
{
char* name; // 節點名
int n_children; // 子節點個數
int level; // 記錄該節點在多叉樹中的層數
struct node_t** children; // 指向其自身的子節點,children一個數組,該數組中的元素時node_t*指針
} NODE; // 對結構體重命名
// 將多叉樹中的節點,按照深度進行輸出,實質上實現的是層次優先遍歷
void levelOrder(NODE* head)
{
NODE* p = NULL;
QUEUE* q = NULL; // 定義一個隊列
STACK* s = NULL; // 定義一個棧
int i = 0;
q = QUEUEinit(100); // 將隊列初始化大小為100
s = STACKinit(100); // 將棧初始化大小為100
head->level = 0; // 根節點的深度為0
// 將根節點入隊列
QUEUEenqueue(q, head);
// 對多叉樹中的節點的深度值level進行賦值
// 采用層次優先遍歷方法,借助於隊列
while (QUEUEempty(q) == 0) // 如果隊列q不為空
{
QUEUEdequeue(q, &p); // 出隊列
for (i = 0; i < p->n_children; ++i)
{
p->children[i]->level = p->level + 1; // 對子節點深度進行賦值:父節點深度加1
QUEUEenqueue(q, p->children[i]); // 將子節點入隊列
}
STACKpush(s, p); // 將p入棧
}
while (STACKempty(s) == 0) // 不為空
{
STACKpop(s, &p); // 彈棧
fprintf(stdout, " %d %s\n", p->level, p->name);
}
QUEUEdestroy(q); // 消毀隊列
STACKdestroy(s); // 消毀棧
}
29、設 h 是帶表頭結點的單鏈表的頭指針,請設計一個逆置這個單鏈表的程序。
typedef struct node
{
int data;
struct node *link
}LNode;
void invert(LNode *h)
{
LNode *s,*p;
p=h->link; //p指針用於記錄當前訪問節點
h->link=NULL; //h置為NULL是為了重新建立一個逆序鏈表而准備的頭節點
while(p!=NULL)
{
s=p; //s用於記錄當前訪問的節點
p=p->link; //p用於指向后面斷開鏈表的第一個節點
s->link=h->link; //將s指向的節點插入到頭節點后面
h->link=s; //將頭節點指針指向第一個節點s
}
}
30、以二叉鏈表為二叉樹的存儲結構,寫一算法計算葉子結點個數
typedef struct BiTNode
{
TDataType data;
struct BiTNode *lchild,*rchild;
}BiTree;
void countLeaf(BiTNode *t,int &count)
{
if(t!=NULL) //不空的情況下
{
if(t->lchild==NULL && t-rchild==NULL)
{
count++;
countLeaf(t->lchild);
countLeaf(t->rchild);
}
}
}
31、設有一個帶頭結點的單鏈表h,數據項遞減有序。寫一算法,重新排列鏈表,使數據項遞增有序,要求時間復雜度O(n)
//本質上是將單鏈表逆置,不同的問法罷了
typedef struct node
{
int data;
struct node *link
}LNode;
void invert(LNode *h)
{
LNode *s,*p;
p=h->link; //p指針用於記錄當前訪問節點
h->link=NULL; //h置為NULL是為了重新建立一個逆序鏈表而准備的頭節點
while(p!=NULL)
{
s=p; //s用於記錄當前訪問的節點
p=p->link; //p用於指向后面斷開鏈表的第一個節點
s->link=h->link; //將s指向的節點插入到頭節點后面
h->link=s; //將頭節點指針指向第一個節點s
}
}
32、設計二叉樹先序、中序、后序遍歷的遞歸算法
//先序
void preOrder(BTNode *b)
{
if(b!=NULL)
{
printf("%c",b->data);
preOrder(b->lchild);
preOrder(b->rchild);
}
}
//中序
void inOrder(BTNode *b)
{
if(b!=NULL)
{
inOrder(b->lchild);
printf("%c",b->data);
inOrder(b->rchild);
}
}
//后序
void postOrder(BTNode *b)
{
if(b!=NULL)
{
postOrder(b->lchild);
postOrder(b->rchild);
printf("%c",b->data);
}
}
33、設計二叉樹先序、中序、后序遍歷的非遞歸算法
//先序
void preOrder(BTNode *b)
{
BTNode *p;
SqStack *st; //定義棧指針st
InitStack(st); //初始化棧
if(b!=NULL)
{
Push(st,b); //根節點進棧
while(!StackEmpty(st)) //棧不為空時循環
{
Pop(st,p); //退棧結點p並訪問
printf("%c",p->data);
if(p->rchild!=NULL) //有右孩子進棧
Push(st,p->rchild);
if(p->lchild!=NULL) //有左孩子進棧
Push(st,p->lchild);
}
printf("\n");
}
DestroyStack(st);
}
//中序
void inOrder(BTNode *b)
{
BTNode *p;
SqStack *st;
InitStack(st);
p=b;
while(!SatckEmpty(st)||p!=NULL)
{
while(p!=NULL) //掃描結點p的所有左下結點並進棧
{
Push(st,p); //結點p進棧
p=p->lchild; //移動到左孩子
}
if(!StackEmpty(st))
{
Pop(st,p); //出棧結點p
printf("%c",p->data); //訪問結點p
p=p->rchild; //轉向處理其右子樹
}
}
printf("\n");
DestroyStack(st);
}
//后序
void postOrder(BTNode *b)
{
BTNode *p,*r;
bool flag;
SqStack *st;
InitStack(st);
p=b;
do
{
while(p!=NULL) //掃描結點p的所有左下結點並進棧
{
Push(st,p); //結點p進棧
p=p->lchild; //移動到左孩子
}
r=NULL; //r指向剛訪問的結點,初始時為空
flag=true; //flag為真表示正在處理棧頂結點
while(!StackEmpty(st)&&flag)
{
GetTop(st,p); //取出當前棧頂結點p
if(p->rchild==r) //若結點p的右孩子為空或為剛剛訪問過的結點
{
printf("%c",p->data); //訪問結點p
Pop(st,p);
r=p; //r指向剛訪問過的結點
}
else
{
p=p->rchild; //轉向處理其右子樹
flag=false; //表示當前不是處理棧頂結點
}
}
}while(!StackEmpty(st)); //棧不空循環
printf("\n");
DestroyStack(st);
}
34、設計二叉樹的層序遍歷
void levelOrder(BTNode *b)
{
BTNode *p;
SqQuene *qu;
InitQueue(qu);
enQuenu(qu,b); //根節點指針進入隊列
while(!QueueEmpty(qu)) //隊不為空循環
{
deQueue(qu,p); //出隊結點p
printf("%c",p->data); //訪問結點p
if(p->lchild!=NULL) //有左孩子時將其進隊
enQueue(qu,p->lchild);
if(p->rchild!=NULL) //有右孩子時將其進隊
enQueue(qu,p->rchild);
}
}
35、線性表的插入和刪除操作
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
//插入
Status insert(LinkList &L,int i,ElemType e)
{
p=L; j=0;
while(p&&j<i-1);
{
p=p->next;
++j;
}
if(!p||j>i-1)
{
return ERROR;
}
s=(LinkList)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
return OK;
}
//刪除
Status delete(LinkList &L,int i,ElemType &e)
{
p=L; j=0;
while(p->next&&j<i-1)
{
p=p->next;
++j;
}
if(p->next||j>i-1)
return ERROR;
q=p->next;
p->next=q->next;
e=q->data;
free(q);
return OK;
}
