数据结构期中复习

一、绪论

1.数组中按值查找元素

cpp 复制代码
int Search(int a[],int n,int k){
    for(int i=1;i<=n;i++){
        if(a[i]==k){
           return i;
        }
    }
    return 0;
}

2.找最大值和次大值

cpp 复制代码
void FindMax(int a[],int n,int *pmax1,int *pmax2){
    if(a[1]>a[2]){
        *pmax1=a[1];
        *pmax2=a[2];
    }
    else{
        *pmax1=a[2];
        *pmax2=a[1];
    }
    for(int i=3;i<=n;i++){
        if(a[i]>*pmax1){
            *pmax2=*pmax1;
            *pmax1=a[i];
       }
        else if(a[i]>*pmax2){
            *pmax2=a[i];
        }
    }
}

二、线性表

1.顺序表的逆置

cpp 复制代码
void reverse(SeqList *q){
    int temp,i;
    for(i=0;i<q->length/2;i++){
        temp=q->elem[i];
        q->elem[i]=q->elem[q->length-i-1];
        q->elem[q->length-i-1]=temp;
    }
}

2.单链表的逆置

cpp 复制代码
void reverse(SeqList *q){
    int temp,i;
    for(i=0;i<q->length/2;i++){
        temp=q->elem[i];
        q->elem[i]=q->elem[q->length-i-1];
        q->elem[q->length-i-1]=temp;
    }
}

3.找出顺序表中的最小值

cpp 复制代码
int FindMin(SeqList *q ) {
 int i=0;
 int min = q->elem[i];
 for (i = 1; i < q->length; i++) {
   if (q->elem[i] < min) {
     min = q->elem[i];
   }
 }

    for(i=0;i<q->length;i++){
        if(min==q->elem[i])
            break;
    }
 return i;
}

4.删除顺序表中的指定值元素

cpp 复制代码
void DeleteX(SeqList *q,ElemType x){
    int flag=0;
    for(int i=0;i<q->length;i++){
        if(q->elem[i]!=x){
           q->elem[flag]=q->elem[i];
            flag++;
        }       
    }
    q->length=flag;
}

5.删除循环链表中已知结点的前驱

cpp 复制代码
void DelPrior(LNode *s){
	int a;
	LNode *p,*q;//q为要删除结点,即s的前驱;p为q的前驱结点 
	p=q=s;
	while(q->next!=s){
		q=q->next;
	}
	while(p->next!=q)
	p=p->next;
	a=q->data;
	p->next=s;
	free(q);
}

6.从单链表LA指定位置删除连续n个元素并插入单链表LB的指定位置

cpp 复制代码
void MoveLaToLb(LinkList *pa,int i,int len,LinkList *pb,int j) {
// m:遍历链表L;n:被删除链表头;p:被删除链表尾;q:遍历链表LB;r:若i不为1,则为被删除链表头结点的前一个元素
    LinkList m, n, p, q, r;
    int length = 1;
    // 遍历LA记录链表长度
    m = *pa;
    while (m) {
        length++;
        m = m->next;
    }
    // 若不存在第i个元素或第i个元素后不足len个元素,则返回
    if (i + len > length)
        return;
    // 遍历LB记录链表长度
    q = *pb;
    length = 0;
    while (q) {
        length++;
        q = q->next;
    }
    // 若不存在第j个元素则返回
    if (j > length)
        return;
    m = *pa;
    // 1.从首元素开始删除
    if (i == 1) {
    // n标记被删除链表头结点
        n = m;
        for (int k=0;k<len-1;k++) {
            m = m->next;
        }
    // p标记被删除链表尾结点
        p = m;
    // LA链表重构,链表头结点为被删除尾元素的下一结点
        *pa = m->next;
    }
    else {
    // 2.从中间元素开始删除
        for (int k=0;k<i-2;k++) {
            m = m->next;
        }
    // r用来标记被删除链表头结点的前一结点(方便重新连接LA链表)
        r = m;
    // n标记被删除链表头结点
        n = m->next;
        for (int k=0;k<len;k++) {
            m = m->next;
        }
    // p标记被删除链表尾结点
        p = m;
    // 重新连接LA链表
        r->next = p->next;
    }
    
    q = *pb;
    if (!j) {
    // 1.头插:直接连接LB头结点
        p->next = q;
    // LB头结点设置为n
        *pb = n;
    }
    else {
        for (int k=0;k<j-1;k++) {
            q = q->next;
        }
    // 2.从中间插入(先连接右边,再连接左边)
        p->next = q->next;
        q->next = n;
    }
}

7.两个单链表元素的交叉合并

cpp 复制代码
LinkList CombineList(LinkList La,LinkList Lb)
{
    LNode *p,*q,*r;
    LinkList Lc;//建立头指针
    int m=0,n=0;
    p = La->next;
    q = Lb->next;
  
    while(p)
    {
        ++m;
        p = p->next;//遍历La链表,求出La的长度
    }
    while(q)
    {
        ++n;
        q = q->next;//遍历Lb链表,求出La的长度
    }
    p = La->next;//因为遍历过后p,q都为空,所以需要让他们重新指向第一个节点
    q = Lb->next;
    
    if(m <= n)
    {
    	Lc = La;//m <= n,说明此时La链表比Lb链表短,那么先从La开始,
        r = Lc;          //让Lc指向La所指的,就是说从La开始,就不用申请空间
                         //建立新的链表了
        while(p && q)
        {
            r->next = p;//有头节点,r就只向p,然后p后移,r再指向q,q后移
            r = p;        //直到p为空,因为p短,先结束
            p = p->next;
            r->next = q;
            r = q;
            q = q->next;
        }
       
          while(q)
          {
                r->next = q;//p执行完了,剩下的都是q
                r = q;
                q = q->next;
           }
          free(Lb);  
    }
    else
    {
    	Lc = Lb;
        r = Lc;
        while(p && q)
        {
            r->next = q;
            r = q;
            q = q->next;
            r->next = p;
            r = p;
            p = p->next;
           
        }
        
        while(p)
        {
            r->next = p;
            r = p;
            p = p->next;
        }
        free(La);
    }

    return (Lc);
}    

三、栈和队列

1.使用栈进行回文判断

cpp 复制代码
int IsPalindrome(char s[]){
    int len = strlen(s);
    SeqStack *stack = InitStack();
    int mid = len/2;
    for(int i=0;i<mid;i++){
        Push(stack,s[i]);
    }
    if(len%2!=0)
        mid++;
    for(int i=mid;i<len;i++){
        char flag;
        if(Pop(stack,&flag)==FALSE)
            return 0;
        if(flag!=s[i])
            return 0;
    }
    return 1;   
}

2.判断表达式中括号是否匹配

cpp 复制代码
int IsBracketMatch(char *str){
    SeqStack *stack = InitStack();
    char flagChar,leftChar;
    for(int i=0;(flagChar=str[i])!='\0';i++){
        if(flagChar=='['||flagChar=='{'||flagChar=='('){
            Push(stack,flagChar);
        }
        else if(flagChar==']'||flagChar=='}'||flagChar==')')
        {
            if(IsEmpty(stack))
                return 0;
            Pop(stack,&leftChar);  
            if((flagChar==']'&&leftChar!='[')||
              (flagChar=='}'&&leftChar!='{')||
              (flagChar==')'&&leftChar!='('))
                return 0;
        }
    } 
    return IsEmpty(stack)?1:0;
}

3.队列的操作集合(带尾指针的循环链表)

cpp 复制代码
// 初始化队列:创建头节点,尾指针指向头节点,头节点的next指向自身
CirLinkQueue InitQueue() {
    LNode *head = (LNode *)malloc(sizeof(LNode));
    // 空队列中,头节点的next指向自身
    head->next = head;
    return head;
}
// 判断队列是否为空:头节点的next指向自身则为空
int IsEmptyQueue(CirLinkQueue Q) {
    // 队列为空的条件:尾指针的next(头节点)的next指向自身
    return (Q->next->next == Q->next) ? 1 : 0;
}

// 入队操作:在尾指针后插入新节点,并更新尾指针
int EnQueue(CirLinkQueue *Q, DataType x) {
    // 创建新节点
    LNode *newNode = (LNode *)malloc(sizeof(LNode));
    newNode->data = x;
    // 新节点的next指向头节点(保持循环特性)
    newNode->next = (*Q)->next;
    // 原尾节点的next指向新节点
    (*Q)->next = newNode;
    // 更新尾指针为新节点
    *Q = newNode;
    return 1; 
}

// 出队操作:删除头节点后的第一个节点(队头),并返回其值
int DelQueue(CirLinkQueue *Q, DataType *x) {
    if (IsEmptyQueue(*Q)) {
        return 0;
    }
    // 找到队头节点(头节点的next)
    LNode *head = (*Q)->next;
    LNode *front = head->next;
    
    // 获取队头元素的值
    *x = front->data;
    
    // 更新头节点的next,跳过队头节点
    head->next = front->next;
    
    // 若删除的是最后一个节点,更新尾指针为头节点
    if (front == *Q) {
        *Q = head;
    }
    // 释放队头节点的内存
    free(front);
    return 1; // 出队成功
}

4.循环链表的操作集合(只设rear和quelen)

cpp 复制代码
int IsEmptyQueue(SeQueue *Q){
    if(Q->quelen==0) return 1;
    return 0;
}
int IsFullQueue(SeQueue *Q){
    if(Q->quelen==MAXSIZE) return 1;
    return 0;
}
int EnQueue(SeQueue *Q,ElemType x){
    if(IsFullQueue(Q))  return 0;
    Q->rear=(Q->rear+1)%MAXSIZE;
    Q->elem[Q->rear]=x;
    Q->quelen++;
    return 1;
}

int DelQueue(SeQueue *Q,ElemType *x){
    if(IsEmptyQueue(Q)) return 0;
    int front=(Q->rear-Q->quelen+1+MAXSIZE)%MAXSIZE;
    *x=Q->elem[front];
    Q->quelen--;
    return 1;
}

5.循环队列的操作集合(增设tag)

cpp 复制代码
SeqQueue * InitQueue(){
    SeqQueue *Q=(SeqQueue *)malloc(sizeof(SeqQueue));
    Q->rear=0,Q->front=0,Q->tag=0;
    return Q;
}
int IsEmptyQueue(SeqQueue *Q){
    if((Q->rear==Q->front)&&Q->tag==0) return 1;
    return 0;
}
int IsFullQueue(SeqQueue *Q){
    if((Q->rear==Q->front)&&Q->tag==1) return 1;
    return 0;
}
int EnQueue(SeqQueue *Q,ElemType x){
    if(IsFullQueue(Q)) return 0;
    Q->rear=(Q->rear+1)%MAXSIZE;
    Q->elem[Q->rear]=x;
    Q->tag=1;
    return 1;
}
int DelQueue(SeqQueue *Q,ElemType *x){
    if(IsEmptyQueue(Q)) return 0;
    Q->front=(Q->front+1)%MAXSIZE;
    *x=Q->elem[Q->front];
    Q->tag=0;
    return 1;
}

六、树

1.二叉树中求度为2的结点的个数

cpp 复制代码
int Degree2(BiTree  bt){
     if(bt==NULL) return 0;
    int sum=0;
    if(bt->Lchild!=NULL&&bt->Rchild!=NULL) 
        sum++;
    return sum+Degree2(bt->Lchild)+Degree2(bt->Rchild);
}

2.交换二叉树的左右子树

cpp 复制代码
void SwapLR(BiTree bt){
    BiTree t;
    if(bt==NULL) return ;
    t=bt->Lchild;
    bt->Lchild=bt->Rchild;
    bt->Rchild=t;
    SwapLR(bt->Lchild);
    SwapLR(bt->Rchild);
}

3.二叉树的先序输出各结点及其层次

cpp 复制代码
void  PreOrderLayer (BiTree bt, int lay){
    if(bt==NULL) return ;
    printf("(%c,%d)",bt->data,lay);
    PreOrderLayer(bt->Lchild,lay+1);
    PreOrderLayer(bt->Rchild,lay+1);
}

4.求树(或森林)的叶子结点数

cpp 复制代码
int NumOfLeaf(CSTree  rt){
    if(rt==NULL) return 0;
    int count=0;
    if(rt->FirstChild==NULL) count++;
    return count+NumOfLeaf(rt->FirstChild)+NumOfLeaf(rt->NextSibling);
}

5. 求树(或森林)的高度

cpp 复制代码
int GetHeight (CSTree rt){
    if(rt==NULL) return 0;
    int child_h=1+GetHeight(rt->FirstChild);
    int next_h=GetHeight(rt->NextSibling);
    return child_h>next_h?child_h:next_h;
}
相关推荐
Nebula_g23 分钟前
C语言应用实例:背包DP1(Bone Collector、Piggy-Bank、珍惜现在,感恩生活)
算法
roman_日积跬步-终至千里26 分钟前
【模式识别与机器学习(5)】主要算法与技术(中篇:概率统计与回归方法)之逻辑回归(Logistic Regression)
算法·机器学习·回归
Promise4856 小时前
贝尔曼公式的迭代求解笔记
笔记·算法
fish_xk6 小时前
数据结构之二叉树中的堆
数据结构
福尔摩斯张7 小时前
Linux进程间通信(IPC)机制深度解析与实践指南
linux·运维·服务器·数据结构·c++·算法
你好~每一天7 小时前
未来3年,最值得拿下的5个AI证书!
数据结构·人工智能·算法·sqlite·hbase·散列表·模拟退火算法
杰克尼7 小时前
3. 分巧克力
java·数据结构·算法
zmzb01038 小时前
C++课后习题训练记录Day39
数据结构·c++·算法
Ayanami_Reii8 小时前
进阶数学算法-取石子游戏(ZJOI2009)
数学·算法·游戏·动态规划·区间dp·博弈论
一只小小汤圆8 小时前
已知圆弧的起点、终点、凸度 求圆弧的圆心
算法