C语言数据结构算法学习记录
小白初学,记录学习,欢迎指正!
一、数组-插入排序
已知两个定长数组,它们分别存放两个非降序有序序列,请编写算法把第二个数组序列中的数逐个插入到前一个数组序列中,完成后两个数组中的数分别有序(非降序)并且第一数组中所有的数都不大于第二个数组中的任意一个数。注意,不能另开辟数组,也不能对任意一个数组进行排序操作。例如:
第一个数组为:4,12,28
第二个数组为:1,7,9,29,45
输出结果为:1,4,7 ——第一个数组
9,12,28,29,45 ——第二个数组
(以下两版本基本一致,看懂其一即可,附上全部代码)
- 版本1
# include <stdio.h>
void print(int t[], int len)
{
int i;
printf("数组:\n");
for(i=0;i<len;i++)
printf("%d ",t[i]);
printf("\n");
}
int main(void)
{
int a[3] = {4,12,28};
int b[5] = {1,7,9,29,45};
int a_len = sizeof(a)/sizeof(a[0]);
int b_len = sizeof(b)/sizeof(b[0]);
int temp1;
int temp2;
int a_count;
int b_count;
while (a[a_len-1] >b[0]){ //a末元素与b首元素比较
temp1=a[a_len-1];
temp2=b[0];
a_count=a_len-1;//记下索引
while (a_count>0&&a[a_count-1]>=temp2) //a数组倒序与 b首元素比较
{
a[a_count]=a[a_count-1]; //小于b首元素则该元素后移
a_count--; //索引前移
}
a[a_count]=temp2;
b_count=0;
while (b_count<b_len&&b[b_count+1]<temp1) //b数组顺序与 a末元素比较
{
b[b_count]=b[b_count+1]; //小于a末元素则该元素前移
b_count++; //索引后移
}
b[b_count]=temp1; //指针指到b数组末 或 b数组某元素大于等于 a[lenA-1] ,将a[lenA-1]放到该位置
}
print(a,a_len);
print(b,b_len);
}
- 版本2
# include <stdio.h>
void sort(int *, int , int *, int);
void print(int *, int);
int main(void)
{
int ar[3] = {4,12,28};
int br[5] = {1,7,9,29,45};
int ar_len = sizeof(ar)/sizeof(ar[0]);
int br_len = sizeof(br)/sizeof(br[0]);
sort(ar,ar_len,br,br_len);
}
/* 已知 两非降序定长数组a,b,及其长度;数组输出函数print(int *, int) */
void sort(int a[], int lenA, int b[], int lenB)
{
int temp1, temp2;
int *ta,*tb;
while (a[lenA-1] >b[0]){ //a末元素与b首元素比较
temp1=a[lenA-1]; //保存a末元素值
temp2=b[0]; //保存b首元素值
ta=a+lenA-1; //a指针移到末尾
while( ta>a && *(ta-1)>=temp2) //a数组倒序与 b首元素比较
{
*ta=*(ta-1); //小于b首元素则该元素后移
ta--; //指针前移
}
*ta=temp2; //指针指到a数组首 或 a数组某元素小于 b[0] ,将b[0]放到该位置
tb=b;
while(tb<(b+lenB-1) && *(tb+1)<temp1){ //b数组顺序与 a末元素比较
*tb=*(tb+1); //小于a末元素则该元素前移
tb++; //指针后移
}
*tb=temp1; //指针指到b数组末 或 b数组某元素大于等于 a[lenA-1] ,将a[lenA-1]放到该位置
}
print(a,lenA);
print(b,lenB);
}
void print(int t[], int len)
{
int i;
printf("数组:\n");
for(i=0;i<len;i++)
printf("%d ",t[i]);
printf("\n");
}
二、统计出单链表HL中结点的值等于给定值X的结点数。
int CountX(LNode* HL, ElemType X){
LNode* p;
int count=0;
if(HL==NULL) return 0;
p=HL->next;
while(p->next!=NULL){
if(p->data==X) count++;
p=p->next;
}
return count;
}
三、删除前驱结点
假设长度大于1的循环单链表中,既无头结点也无头指针,p为指向该链表中某一结点的指针,编写一个函数删除该结点的前驱结点。
/*长度大于1的循环单链表已建好*/
void del(LNode* p){
LNode *q, *s1, *s2;
//q搜素p的前驱的前驱,s1搜素p的前驱,s2搜索p;查找完毕删s1,将s2赋给q->next;
q=p;
s1=q->next;
s2=s1->next;
while(s2!=p){
s2=s2->next;
s1=s1->next;
q=q->next;
}
q->next=s2;
delete(s1);
}
四、实现有头结点单链表的原地逆置
个人分析画图时的录屏:点此观看
void nizhi(Linklist h){
Listnode *p=head->next;
Listnode *q;
head->next=NULL;
while(p){
q=p->next;
p->next=head->next;
head->next=p;
p=q;
}
}
五、 链表_表头变表尾代码分析题
个人分析画图时的录屏:点此观看
请回答下列问题:
(1)说明语句S1的功能;
(2)说明语句组S2的功能;
LinkList mynote(LinkList L){ //L是不带头结点的单链表的头指针
if(L&&L->next){
q=L;
L=L->next;
p=L;
S1: while(p->next) p=p->next;
S2: p->next=q; q->next=NULL;
}
return L;
}
(1)找到表尾存储地址,并用p指向表尾;
(2)p->next=q 将表尾结点的指针域存放表头结点的存储地址,即表尾指向表头
q->next=NULL 原表头指针域置空,即将表头变成表尾;