数据结构题目练习

29 篇文章 8 订阅
17 篇文章 2 订阅

顺序表的就地逆置

编写一个函数,实现顺序表的就地逆置,也就是说利用原表的存储空间将顺序表(a1,a2…an),逆置为(an,an-1…a1)

#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10//静态顺序表的最大空间

typedef struct
{
    int *base;
    int length;
}Sqlist;//顺序表


void reverseSQ(Sqlist *l)   
{   //实现顺序表l的就地逆置
    int low = 0, high = l->length - 1;
    int buf, i;


    for (int  i = 0; i < l->length / 2; i++)
    {   //循环l->length/2次
        buf = l->base[low];
        l->base[low] = l->base[high];
        l->base[high] = buf;
        low++;
        high--;
    }
}
int main(int argc, char const *argv[])
{
    Sqlist l;
    int i, data;

    l.base = (int*)malloc(sizeof(int) * MAXSIZE);
    l.length = 0;//创建顺序表
    if (!l.base)
    {   //分配内存失败
        printf("error!\n");
    }

    //输入数据

    for (i = 0; i < MAXSIZE; i++)
    {
        scanf("%d", &l.base[i]);
        l.length++;
    }

    //输出数据

    for (i = 0; i < l.length; i++)
    {
        printf("%d ", l.base[i]);
    }
    printf("\n");

    reverseSQ(&l);//就地逆置

    for (i = 0; i < l.length; i++)
    {
        printf("%d ", l.base[i]);
    }

    system("pause");
    return 0;
}

动态数列排序

实现这样的功能:从键盘上输入任意个整数,以0作为结束标志,对这个整数序列从小到大排序,并输出排序后的结构

#include <stdio.h>
#include <stdlib.h>

//定义链表的结点类型
typedef struct node
{
    int data;
    struct node *next;
}LNode, *LinkList;

//创建一个长度为n的链表
LinkList creatList(int n)
{
    LinkList p, q, list = NULL;
    int elem, i;

    for (i = 0; i < n; i++)
    {
        scanf("%d", &elem);
        p = (LinkList)malloc(sizeof(LNode));
        if (!p)
        {
            return NULL;
        }
        p->data = elem;
        p->next = NULL;
        if (list == NULL)
        {
            list = p;//第一个结点
        }
        else
        {
            q->next = p;
        }
        q = p;
    }
    return list;
}

//向链表中插入结点,并向该结点的数据域中存放数据
void insertList(LinkList *list, LinkList q, int elem)
{
    LinkList p;
    p = (LinkList)malloc(sizeof(LNode));
    if (!p)
    {
        return ;
    }
    p->data = elem;
    if (!*list)
    {   //如果首结点为空
       *list = p;
       p->next == NULL; 
    }
    else
    {   //向后插入
        p->next = q->next;
        q->next = p;
    }
}

//基于链表冒泡排序
void bubbleSort(LinkList list)
{
    LinkList p = list;
    int temp, i, j, k = 0;

    while (p)
    {
        k++;
        p = p->next;
    }//k为链表元素个数

    p = list;
    for (i = 0; i < k - 1; i++)
    {
        for (j = 0; j < k - 1 - i; j++)
        {
            if (p->data > p->next->data)
            {   //与下一个位置进行比较
                temp = p->data;
                p->data = p->next->data;
                p->next->data = temp;
            }
            p = p->next;
        }
        p = list;//指针重新指向开头
    }
}

//打印出排序后的新链表
void print(LinkList list)
{
    while (list)
    {
        printf("%d ", list->data);
        list = list->next;
    }
}

int main(int argc, char const *argv[])
{
    LinkList q, r;
    int elem;

    q = r = creatList(1);//创建一个链表结点,q和r都指向这个结点

    scanf("%d", &elem);
    while (elem)
    {   //循环输入数据同时插入结点
        insertList(&q, r, elem);
        r = r->next;
        scanf("%d", &elem);
    }

    bubbleSort(q);
    print(q);

    system("pause");
    return 0;
}

在原表空间上实现归并

有两个按元素值递增的有序排列的链表list1和list2,现需要将两个链表合并一个按元素值递增的有序链表list3。要求利用原表空间的结点空间构造新表。

#include <stdio.h>
#include <stdlib.h>

typedef struct node
{
    int data;
    struct node *next;
}LNode, *LinkList;

//创建一个长度为n的链表
LinkList creatLinkList(int n)
{
    LinkList p, r, list = NULL;
    int elem, i;

    for (i = 0; i < n; i++)
    {
        scanf("%d", &elem);
        p = (LinkList)malloc(sizeof(LNode));
        if (!p)
        {
            return NULL;
        }
        p->data = elem;
        p->next = NULL;
        if (!list)
        {
            list = p;
        }
        else
        {
            r->next = p;
        }
    }
    return list;
}

//向链表中插入结点,并向该结点的数据域中存放数据
void insertList(LinkList *list, LinkList q, int elem)
{
    LinkList p;
    p = (LinkList)malloc(sizeof(LNode));
    p->data = elem;
    if (!p)
    {
        return ;
    }
    if (!*list)
    {
        *list = p;
        p = p->next;
    }
    else
    {
        p->next = q->next;
        q->next = p;
    }
}

//将p指向的结点插入到q1,q2所指向的结点当中
void insertNode(LinkList *q1, LinkList *q2, LinkList *p, LinkList *l2)
{
    if (*q1 == *q2)
    {   //l1链表第一个结点内容小于来l2链表第一个结点内容,特判
        (*p)->next = *q2;
        *l2 = *q2 = *q1 = *p;
    }
    else
    {
        (*q2)->next = *p;
        (*p)->next = *q1;
        (*q2) = (*q2)->next;
    }
}

//将l1,l2原空间有序归并,用l3返回
void mergeLink(LinkList l1, LinkList l2, LinkList *l3)
{
    LinkList p, q1, q2;
    q1 = q2 = l2;//q1, q2指向l2链表
    p = l1;//p指向l1链表
    while (p && q1)
    {
        if (p->data >= q1->data)
        { 
            q2 = q1;
            q1 = q1->next;
        }
        else
        {
            l1 = l1->next;
            insertNode(&q1, &q2, &p, &l2);
            p = l1;
        }
        /*
            p指向l1链表,q1,q2指向l2链表,q2始终在q1后一个位置
            比较p->data 和 q1->data ,
            1.如果p->data >= q1->data, q1,q2指向其下一个位置
            2.如果p->data < q1->data, 将p插入q1,q2之间
            直到某一链表为空结束
        */
    }
    if (!q1)
    {
        q2->next = p;
    }
    /*
        如果l1链表为空,那么l1已经完全插入合并到l2中
        如果l2链表为空,则讲l2尾指针指向l1连接
    */
    *l3 = l2;//l2首结点赋给l3
}

//打印链表
void print(LinkList list)
{
    while (list)
    {
        printf("%d ", list->data);
        list = list->next;
    }
}

int main(void)
{
    LinkList l1, l2, l3, q;
    int elem;

    //创建链表l1
    q = l1 = creatLinkList(1);
    scanf("%d", &elem);
    while(elem)
    {
        insertList(&l1, q, elem);
        q = q->next;
        scanf("%d", &elem);
    }

    //创建链表l2
    q = l2 = creatLinkList(1);
    scanf("%d", &elem);
    while(elem)
    {
        insertList(&l2, q, elem);
        q = q->next;
        scanf("%d", &elem);
    }

    //归并链表
    mergeLink(l1, l2, &l3);
    //打印合并链表
    print(l3);

    system("pause");
    return 0;
}

约瑟夫环

编号1, 2, 3…n的n个人按顺时针方向坐一圈,每个人手中持有一个密码。开始时任选一个正整数作为报数的上限m,从第一个人开始按顺时针方向自1开始顺序表报数,报道m停止,报到m的人出列,将他手中的密码作为新的报数上限m,从顺时针方向上的下一个开始重新从1报数,如此报数下去,求最后剩下的那个人的最初编号是多少。
解决约瑟夫环问题,最关键的是要选取好存放数据的数据结构。最简单的方法是使用循环链表作为存储结构,通过链表的删除操作实现报数人的出列,通过对链表的循环遍历,实现顺时针报数。

#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
    int number;//编号
    int psw;//个人密码
    struct node *next;
}LNode, *LinkLisk;

//向链表list中q指向结点后面插入一个新结点
void insertList(LinkLisk *list, LinkLisk q, int data1, int data2)
{
    LinkLisk p;
    p = (LinkLisk)malloc(sizeof(LNode));
    p->number = data1;
    p->psw = data2;
    if(!*list)
    {
        *list = p;
    }
    else
    {
        p->next = q->next;
        q->next = p;
    }   
}

//创建一个约瑟夫环
void creatJoseph(LinkLisk *jsp, int n)
{   
    LinkLisk q = NULL, list = NULL;
    int i, elem;
    
    for (i = 0; i < n; i++)
    {
        scanf("%d", &elem);
        insertList(&list, q, i + 1, elem);//向q指向的结点后插入新的结点
        if (i == 0)
        {
            q = list;
        }
        else
        {
            q = q->next;
        }
    }
    q->next = list;//形成循环链表
    *jsp = list;
}

//
void exJosph(LinkLisk *jsp, int m)
{
    LinkLisk p, q;
    int i;

    p = q = *jsp;
    while (q->next != p)
    {
        q = q->next;//q指向p的前一个结点
    }
    while (p->next != p)
    {
        for (i = 0; i < m - 1; i++)
        {   //p指向要删除的结点,q指向删除结点的前一个结点
            q = p;
            p = p->next;
        }
        q->next = p->next;//删除p指向的结点
        printf("%d ", p->number);//输出出列的数
        m = p->psw;//重置报数上限
        free(p);//释放p指向的结点
        p = q->next;//p指向q的后一个结点
    }
    printf("\nThe last person in the cicrle is %d\n", p->number);
}

int main(void)
{
    LinkLisk jsp;
    int n, m;


    scanf("%d", &n);//输入约瑟夫环人数
    creatJoseph(&jsp, n);


    scanf("%d", &m);//输入约瑟夫环报数上限
    exJosph(&jsp, m);

    system("pause");
    return 0;
}

二进制/八进制转化器

要求从终端输入一串0/1表示的二进制数,用来表示它的八进制表示形式。
进制转化这类运算最简单的办法是使用栈的数据结构,从栈A顶取数每取出3位,转换成一个对应的八进制数,存到新栈B。

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#define STACK_INIT_SIZE 20
#define STACKINCREMENT 10
typedef struct 
{
    char *base;
    char *top;
    int stacksize;
    /* data */
}Stack;

//初始化栈
void initStack(Stack *s)
{
    //内存中开辟一段连续空间作为栈空间
    s->base = (char*)malloc(STACK_INIT_SIZE * sizeof(char));
    if (!s->base)
    {
        exit(0);
    }
    s->top = s->base;
    s->stacksize = STACK_INIT_SIZE;
}

//入栈操作
void push(Stack *s, char elem)
{
    if (s->top - s->base >= STACK_INIT_SIZE)
    {   //栈满追加空间
        s->base = (char*)realloc(s->base, sizeof(char) * (STACK_INIT_SIZE + STACKINCREMENT));
        if (!s->base)
        {
            exit(0);
        }
        s->top = s->base + s->stacksize;
        s->stacksize += STACKINCREMENT;
    }
    *(s->top++) = elem;
}

//出栈操作
void pop(Stack *s, char *elem)
{
    if (s->top == s->base)
    {
        return;
    }
    *elem = *--(s->top);
}

//返回栈s的当前长度
int stackLen(Stack s)
{
    return (s.top - s.base);
}

//销毁栈
void destoryStack(Stack *s)
{
	free(s->base);
	free(s->top);
	s->base = NULL;
	s->top = NULL;
}
int main(void)
{
    Stack a, b;
    char ch;
    int len = stackLen(a);
    int i, j, sum = 0;
    char elem;


    initStack(&a);//创建一个栈用来存2进制字符串
    scanf("%c", &ch);
    while (ch != '#')
    {
        if (ch == '0' || ch == '1')
        {
            push(&a, ch);
        }
        scanf("%c", &ch);
    }

    initStack(&b);//创建一个栈用来存放8进制字符串
    for (i = 0; i < len; i += 3)
    {
        for (j = 0; j < 3; j++)
        {
            pop(&a, &elem);
            sum += (elem - 48) * pow(2, j);
            if (a.base == a.top)
            {
                break;
            }
        }
        push(&b, sum + 48);
        sum = 0;
    }

    while (b.base != b.top)
    {
        pop(&b, &ch);
        printf("%c", ch);
    }

    system("pause");
    return 0;
}

回文字符串

有一种字符序列正读和反读都相同,这种字符序列成为“回文”。从键盘输入一个任意长度的字符串,以#作为结束标志,判断是否是回文。
思路:在输入字符序列时,把输入的字符存到栈和队列中。
重复取栈数据和队列数据,进行比较重复len/2次。

#pragma once
#include <stdlib.h>
#include <stdio.h>
#define STACK_INIT_SIZE 20
#define STACKINCREMENT 10
typedef struct 
{
    char *base;
    char *top;
    int stackSize;
}Stack;
void initStack(Stack *s)
{
    s->base = (char*)malloc(sizeof(char) * STACK_INIT_SIZE);
    if (!s->base)
    {
        return;
    }
    s->top = s->base;
    s->stackSize = STACK_INIT_SIZE;
}
void push(Stack *s, char elem)
{
    if (s->top - s->base >= s->stackSize)
    {
        s->base = (char*)realloc(s->base, sizeof(char) * (STACK_INIT_SIZE + STACKINCREMENT));
        if (!s->base)
        {
            return;
        }
        s->top = s->base + STACK_INIT_SIZE;
        s->stackSize += STACKINCREMENT;
    }
    *(s->top++) = elem;
}
void pop(Stack *s, char *elem)
{
    if (s->top == s->base)
    {
        return;
    }
    *elem = *(--s->top);
}
void destoryStack(Stack *s)
{
	free(s->base);
	free(s->top);
	s->base = NULL;
	s->top = NULL;
}

int stackLen(Stack s)
{
    return s.top - s.base;
}




#pragma once
#include <stdlib.h>
#include <stdio.h>
#define QUEUE_INIT_SIZE 20
#define QUEUEINCREMENT 10
typedef struct queue
{
    char *buffer;
    int top;
    int count;
    int queueSize;
}Queue, *QueuePtr;

void initQueue(QueuePtr p)
{
    p->buffer = (char*)malloc(sizeof(char) * QUEUE_INIT_SIZE);
    if (!p->buffer)
    {
        exit(0);
    }
    p->top = 0;
    p->count = 0;
    p->queueSize = QUEUE_INIT_SIZE;
}

void enQueue(QueuePtr p, char elem)
{
    if (p->count == p->queueSize)
    {
        p->buffer = (char*)realloc(p->buffer, sizeof(char) * (QUEUE_INIT_SIZE + QUEUEINCREMENT));
        p->queueSize += QUEUEINCREMENT;
    }
    p->buffer[p->count++] = elem;
}

void deQueue(QueuePtr p, char *elem)
{
    if (p->count == 0)
    {
        return ;
    }
    *elem = p->buffer[p->top++];
}




#include "Stack.h"
#include "Queue.h"

int main(void)
{
    Queue q;
    Stack s;
    initQueue(&q);
    initStack(&s);
    char ch;
    scanf("%c", &ch);
    while(ch != '#')
    {
        push(&s, ch);
        enQueue(&q, ch);
        scanf("%c", &ch);
    }

    int len = stackLen(s);

    int i;
    char a, b;
    int flag = 0;
    for (i = 0; i < len / 2; i++)
    {
        pop(&s, &a);
        deQueue(&q, &b);
        if (a != b)
        {
            flag = 1;
            break;
        }
    }
    if (flag)
    {
        printf("It is not a circle string!\n");
    }
    else
    {
        printf("It is a circle string!\n");
    }
    system("pause");
    return 0;
}
1.1 单项选择题 1. 数据结构是一门研究非数值计算的程序设计问题中,数据元素的① 、数据信息在计算机中的② 以及一组相关的运算等的课程。 ① A.操作对象   B.计算方法  C.逻辑结构  D.数据映象 ② A.存储结构 B.关系 C.运算 D.算法 2. 数据结构DS(Data Struct)可以被形式地定义为DS=(D,R),其中D是① 的有限集合,R是D上的② 有限集合。 ① A.算法 B.数据元素 C.数据操作 D.数据对象 ② A.操作 B.映象 C.存储 D.关系 3. 在数据结构中,从逻辑上可以把数据结构分成 。 A.动态结构和静态结构 B.紧凑结构和非紧凑结构 C.线性结构和非线性结构 D.内部结构和外部结构 4. 算法分析的目的是① ,算法分析的两个主要方面是② 。 ① A. 找出数据结构的合理性 B. 研究算法中的输入和输出的关系 C. 分析算法的效率以求改进 D. 分析算法的易懂性和文档性 ② A. 空间复杂性和时间复杂性 B. 正确性和简明性 C. 可读性和文档性 D. 数据复杂性和程序复杂性 5. 计算机算法指的是① ,它必具备输入、输出和② 等五个特性。 ① A. 计算方法 B. 排序方法 C. 解决问题的有限运算序列 D. 调度方法 ② A. 可行性、可移植性和可扩充性 B. 可行性、确定性和有穷性 C. 确定性、有穷性和稳定性 D. 易读性、稳定性和安全性 1.2 填空题(将正确的答案填在相应的空中) 1. 数据逻辑结构包括 、 、 和 四种类型,树形结构和图形结构合称为 。 2. 在线性结构中,第一个结点 前驱结点,其余每个结点有且只有 个前驱结点;最后一个结点 后续结点,其余每个结点有且只有 个后续结点。 3. 在树形结构中,树根结点没有 结点,其余每个结点有且只有 个直接前驱结点,叶子结点没有 结点,其余每个结点的直接后续结点可以 。 4. 在图形结构中,每个结点的前驱结点数和后续结点数可以 。 5. 线性结构中元素之间存在 关系,树形结构中元素之间存在 关系,图形结构中元素之间存在 关系。 6. 算法的五个重要特性是__ __ , __ __ , ___ _ , __ __ , _ ___。 7. 分析下面算法(程序段),给出最大语句频度 ,该算法的时间复杂度是__ __。 for (i=0;i<n;i++) for (j=0;j<n; j++) A[i][j]=0; 8. 分析下面算法(程序段),给出最大语句频度 ,该算法的时间复杂度是__ __。 for (i=0;i<n;i++) for (j=0; j<i; j++) A[i][j]=0; 9. 分析下面算法(程序段),给出最大语句频度 ,该算法的时间复杂度是__ __。 s=0; for (i=0;i<n;i++) for (j=0;j<n;j++) for (k=0;k<n;k++) s=s+B[i][j][k]; sum=s; 10. 分析下面算法(程序段)给出最大语句频度 ,该算法的时间复杂度是__ __。 int i=0,s=0; while (s<n) { i++; s+=i; //s=s+i } 11. 分析下面算法(程序段)给出最大语句频度 ,该算法的时间复杂度是__ __。 i=1; while (i<=n) i=i*2;
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值