数据结构(严蔚敏老师c语言第2版)

文章目录

  • 1.顺序表
  • 2.链表
  • 3.栈
    • 3.1顺序栈
    • 3.2链栈
  • 4.队列
    • 4.1顺序循环队列
    • 4.2链式队列

1.顺序表

顺序表的特点:(增、删慢,查找快)
1、随机访问,可以在O(1)时间内找到第 i 个元素。
2、存储密度高,每个节点只存储数据元素。
3、拓展容量不方便(即使动态分配空间时间复杂度也比较高)。
4、插入、删除操作不方便,需要移动大量元素。

#include 
#include
#define Maxsize 100
//定义顺序表的存储结构
typedef struct
{
    int* elem;
    int  length;
}Sqlist;

void Initlist(Sqlist& L);
void CreateSqlist(Sqlist& L, int n);
void menu();
void Getelem(Sqlist& L, int i);
void LocateElem(Sqlist L, int e);
void InsertElem(Sqlist &L, int pos, int e);
void DeleteElem(Sqlist &L, int pos);
void AlterElem(Sqlist L, int pos, int data);
void Display(Sqlist L);
void BubbleSort(Sqlist L);

int main()
{
    Sqlist L;
    Initlist(L);
    printf("请输入5个数:\n");
    CreateSqlist(L, 5);
    while (true)
    {
        menu();
        int d;
        scanf_s("%d", &d);
        switch (d)
        {
        case 1:
            printf("你想找第几个数?\n");
            int pos1;
            scanf_s("%d", &pos1);
            Getelem(L, pos1);
            break;
        case 2:
            printf("你要找哪个数?\n");
            int e;
            scanf_s("%d", &e);
            LocateElem(L, e);
            break;
        case 3:
            printf("在哪个位置添加?添加谁?\n");
            int loc, who;
            scanf_s("%d %d", &loc, &who);
            InsertElem(L, loc, who);
            Display(L);
            break;
        case 4:
            printf("删除第几个数据?\n");
            int pos4;
            scanf_s("%d", &pos4);
            DeleteElem(L, pos4);
            break;
        case 5:
            printf("你要修改哪个位置的数据?改为多少?\n");
            int pos5, data;
            scanf_s("%d %d", &pos5, &data);
            AlterElem(L, pos5, data);
            Display(L);
            break;
        case 6:
            BubbleSort(L);
            Display(L);
        case 7:
            exit(0);
            break;
        default:
            break;
        }
    }
}
void menu()
{
    printf("★☆请选择要使用的功能☆★\n");
    printf("1.按位置找相应的数\n");
    printf("2.按值找对应下标\n");
    printf("3.添加数据\n");
    printf("4.删除数据\n");
    printf("5.修改数据\n");
    printf("6.排序\n");
    printf("7.退出\n");
}
//创空间
void  Initlist(Sqlist& L)
{
    L.elem = new int[Maxsize];
    if (!L.elem)
    {
        exit(OVERFLOW);
    }
    L.length = 0;
}
//初始化放数据
void CreateSqlist(Sqlist& L, int n)
{
    int i;
    for (i = 0; i < n; i++)
    {
        scanf_s("%d", &L.elem[i]);
    }
    L.length = n;
}
//按位找
void Getelem(Sqlist& L, int pos)
{
    if (pos<1 || pos>L.length)
    {
        printf("输入的位置不符合,请重新输入:");
        Getelem(L, pos);
    }
    int e = L.elem[pos - 1];
    printf("这个数为:%d\n", e);
}
//按值找
void LocateElem(Sqlist L, int e)
{
    for (int i = 0; i < L.length; i++)
    {
        if (e == L.elem[i])
        {
            printf("这个数的下标为:%d\n", i);
        }
        else
            printf("不存在该元素!\n");
            break;
    }
}
//插入数据
void InsertElem(Sqlist &L, int pos, int e)
{
    if (pos<1 || pos>L.length)
    {
        printf("输入的位置不符合!\n");
    }
    else if (L.length == 10)
    {
        printf("空间已满,无法插入!\n");
    }
    for (int j = L.length - 1; j >= pos - 1; j--)
    {
        L.elem[j] = L.elem[j - 1];
    }
    L.elem[pos - 1] = e;
    L.length++;
    printf("添加成功");
}
//删除数据
void DeleteElem(Sqlist &L, int pos)
{
    if (pos > 0 && pos <= L.length) {
        int  j;
        for (j = pos; j <= L.length; j++) {
            L.elem[j - 1] = L.elem[j];
        }
        L.length--;
        printf("删除成功!还有%d个元素\n", L.length);
    }
    else
        printf("位置不合理!只有%d个元素\n",L.length);
    Display(L);
}
//修改数据
void AlterElem(Sqlist L, int pos, int data)
{
    if (pos<1 || pos>L.length)
    {
        printf("输入的位置不符合!");
    }
    L.elem[pos - 1] = data;
    printf("修改成功!\n");
}
//打印
void Display(Sqlist L)
{
    if (&L != NULL)
    {
        for (int i = 0; i < L.length; i++)
        {
            printf("%d ", L.elem[i]);
        }
        printf("\n");
    }
//冒泡排序
}
void BubbleSort(Sqlist L)
{
    int temp,flag;
    for (int i = 0; i < L.length-1; i++)            //比较多少趟
    {
        flag = 1;       //有序标记,没一轮的初始值为1
        for (int j = 0; j < L.length - 1 - i; j++) //每趟进行比较多少次
        {
            if (L.elem[j] > L.elem[j + 1]) 
            {
                flag = 0;          //如果进行了交换,则修改标记flag
                temp = L.elem[j];
                L.elem[j] = L.elem[j + 1];
                L.elem[j + 1] = temp;
            }
        }
        if (flag)         //如果flag未被修,则元素已经有序
        { 
            break;
        }

    }
}

2.链表

typedef struct LNode 
{
    int data;//数据域
    struct LNode* next;//指针域
}LNode,*LinkList;//定义两个名字:LNode *p, 则p为指向单链表中某个节点的指针.  LinkList p==LNode* p
                //LinkList p,单链表中某个指针类型的变量    
#include 
#include


//______________________________________________________________________________
//函数声明
void headInsertList(LinkList& L);
void tailInsertList(LinkList& L);
void printList(LinkList& L);
void searchList1(LinkList& L, int n);
void searchList2(LinkList& L, int n);
void deleteList(LinkList& L, int n);
void InsertList(LinkList& L, int index, int x);
void alter(LinkList& L, int n, int m);

//______________________________________________________________________________
void menu() 
{
    printf("请选择功能:\n");
    printf("1、添加元素:\n");
    printf("2、删除元素:\n");
    printf("3、查找元素:\n");
    printf("4、修改元素:\n");
    printf("5、退出!");
}   

int main()
{   
    LinkList L;
    printf("请初始化链表,你选择哪种方式?\n");
    printf("1、头插法\n");
    printf("2、尾插法\n");
    int m1;
    scanf_s("%d", &m1);
    switch (m1)
    {
    case 1:headInsertList(L);
        break;
    case 2:tailInsertList(L);
        break;
    default:
        break;
    }
    while (true) {
        menu();
        printf("请选择:\n");
        int n;
        scanf_s("%d", &n);
        switch (n)
        {
        case 1:printf("在哪个位置添加?添加谁?\n");
            int x, y;
            scanf_s("%d %d", &x, &y);
            InsertList(L, x, y);
            break;
        case 2:printf("删除第几个元素?\n");
            int m2;
            scanf_s("%d", &m2);
            deleteList( L,m2);
            break;
        case 3:printf("你选择那种方式?\n");
                printf("1、按位置查找\n");
                printf("2、按数值查找\n");
            int l;
            scanf_s("%d", &l);
            switch (l)
            {
            case 1:
                printf("查找哪个位置的数?");
                int val;
                scanf_s("%d", &val);
                searchList2(L,val);
                break;
            case 2:printf("查找哪个数?\n\n");
                int val2;
                scanf_s("%d", &val2);
                searchList1(L, val2);
                break;
            default:
                break;
            }
            break;
        case 4:printf("修改第几个元素?改成什么?\n");
            int w,k;
            scanf_s("%d %d", &w,&k);
            alter(L, w, k);
            break;
        case 5:exit(0);
        default:
            break;
        }
    }
}
//尾插法初始化单链表
void tailInsertList(LinkList &L) 
{
    L = new LNode; //先创建一个带头节点的空链表
    L->next = NULL;
    LinkList cur = L;//定义一个尾节点,先指向L
    printf("请输入10个数,以创建单链表(正序):\n");
    for (int i = 0; i < 10; i++) 
    {
        LinkList node = new LNode;
        scanf_s("%d", &node->data);
        node->next = NULL;
        cur->next = node;
        cur = node;
    }
    printf("创建成功!\n");
    printList(L);
}
//头插法初始化单链表
void headInsertList(LinkList &L) 
{
    L = new LNode; //先创建一个带头节点的空链表
    L->next = NULL;
    printf("请输入10个数,以创建单链表(逆序):\n");
    for (int i = 0; i < 10; i++) 
    {
        LinkList node = new LNode;
        scanf_s("%d", &node->data);
        node->next = L->next;
        L->next = node;
    }
    printf("创建成功!\n");
    printList(L);
}

//删除第n个元素
void deleteList(LinkList &L,int n) 
{
    LinkList p, q;
     p = L;  //p指向头节点
    int j = 0;
    while (p->next != NULL && j < n - 1) {  
        p = p->next;
        j++;
    }
    if(p->next!=NULL||(j>n-1))
    {
        printf("位置不合理!\n");
    }
    q = p->next;    //保存被删除节点的地址,以备释放
    if (p)//判断p是否为空指针,避免空指针异常
    {
        p->next = q->next;
    }
    //p指向后面那个节点
    delete q;
    printf("删除成功!\n");
    printList(L);
}
//按值查找
void searchList1(LinkList &L, int n) {
    int j = 1;
    LNode* p = L->next;
    while (p != NULL && p->data != n) {
        p = p->next;
        j++;
    }
    if (p!=NULL||p->data == n) {
        printf("找到了!这是第%d个数\n", j);
    }
}
//按位置查找
void searchList2(LinkList &L,int n) 
{
    if (n < 1 && n>10) {
        printf("位置无效!退出\n");
    }
    LNode* p = L;
    int j = 0;
    while (p != NULL && j < n) {
        p = p->next;
        j++;
    }
    if (j = n) {
        printf("这个数是:%d\n", p->data);
    }
}
//修改元素
void alter(LinkList& L, int n,int m) {
    LNode* p = L;
    if (n > 10)
        printf("位置无效!\n");
    for (int j = 0; j < n; j++) {
        p = p->next;
    }
    p->data = m;
    printf("修改成功!\n");
    printList(L);
}
//添加元素
void InsertList(LinkList &L,int index,int x) {
    LNode* p = L;
    int j = 0;
    while (p!=NULL && j < index - 1) //p不等于NULL,并且还没到要添加元素的位置,则p往后移
    {
        p = p->next;
        j++;
    }
    if (p==NULL || j > index - 1) {   //
        printf("位置不合理,已退出!\n");
    }
    LinkList node = new LNode;
    node->data = x;
    if(p)//判断p是否为空指针,避免空指针异常
    {
        node->next = p->next;
    }
    p->next = node;
    printf("添加成功!\n");
    printList(L);
}
//打印
void printList(LinkList& L)
{
    LinkList cur = L->next;
    while (cur != NULL) {
        printf("%d ", cur->data);
        cur = cur->next;
    }
    printf("\n");
}

3.栈

3.1顺序栈

 1. 定义栈的存储结构
//定义存储结构
typedef struct {
    int* top;//栈顶指针
    int* base;//栈底指针
    int stacksize;//栈可用的最大容量
}SqStack;
//初始化:为顺序栈分配一个最大容量为MAXSIZE的数字空间
void InitStack(SqStack& s) 
{
    s.base = new int[MAXSIZE];//为顺序栈分配一个最大容量为MAXSIZE的空间
    if (!s.base) 
    {
        printf("存储空间分配失败!\n");
    }
    s.top = s.base;//空栈
    s.stacksize = MAXSIZE;
}

2.入栈

void  Push(SqStack& s,int e) 
{
    if (s.top - s.base == MAXSIZE) 
    {    //判断栈是否满
        printf("栈以满,无法入栈!\n");
    }
    else 
    {
        *s.top = e;
        s.top++;  //将e压入栈中,栈顶指针+1,即栈顶指针 指向栈顶元素上面的一块内存空间!
    }
}
  1. 出栈
void Pop(SqStack& s) 
{
    if (s.base == s.top) 
    {
        printf("栈空,无法出栈!\n");
    }
    else
    {
        int e = *(s.top - 1);
        printf("出栈元素为:%d\n", e);
        s.top--;
    }
}

4.取栈顶元素

void ShowTopElem(SqStack s) 
{
    if (s.top != s.base) {
        printf("栈顶元素为:%d\n", *(s.top - 1));
    }
    else {
        printf("栈空!\n");
    }
}

5.打印栈

void DisPlayStack(SqStack s) 
{
    for (int* i = s.top-1; i >= s.base; i--) //从栈顶元素开始,从上往下遍历输出
    {
        printf("%d\n", *i);
    }
}

3.2链栈

1.定义链栈的存储结构

typedef struct StackNode
{
    int data;   
    struct StackNode* next;//指针域
}StcakNode,*LinkStack;   //LinkStack为指向结构体StackNode的指针类型

2.链栈的初始化

void InitStack(LinkStack &S) 
{
    S = NULL;//构造一个空栈S,栈顶指针指向NULL
}

3.入栈

void Push(LinkStack &S,int e) 
{
    LinkStack p = new StackNode;  //生产新的节点
    p->data = e;
    p->next = S;  //p的指针域指向 当前S指向的位置
    S = p;//将S指向p
}

4.出栈

void Pop(LinkStack& S) {
    if (S == NULL) 
    {
        printf("栈中没有元素\n");
        exit(0);
    }
    int e = S->data;
    LinkStack p = S;
    S = S->next;
    delete p;
    printf("出栈成功,出栈元素为:%d\n", e);
}

5.取栈顶元素

int GeyTop(LinkStack S) 
{
    if (S != NULL) 
    {
        return S->data;
    }
}

6.打印栈

void DisPlay(LinkStack S) 
{
    LinkStack temp;
    temp = S;
    while (temp != NULL)
    {
        printf("%d\n", temp->data);
        temp = temp->next;
    }
}

4.队列

4.1顺序循环队列

#include 
//定义队的存储结构
#define MAXSIZE 6
//函数声明------------------------------------------------------
void InitQueue(SqQueue& Q);
void EnterQueue(SqQueue& Q, int e);
void OutQueue(SqQueue& Q);
void GetHead(SqQueue Q);
int  QueueLength(SqQueue Q);
void PrintQueue(SqQueue Q);
//------------------------------------------------------
typedef struct
    {
        int* base;   //存储空间的基地址
        int front;//头指针
        int rear;//尾指针
    }SqQueue;

    int main()
    {
        SqQueue Q;
        InitQueue(Q);
        EnterQueue(Q, 1);
        EnterQueue(Q, 2);
        EnterQueue(Q, 3);
        EnterQueue(Q, 4);
        EnterQueue(Q, 5);
        printf("队长为%d\n", QueueLength(Q));
        OutQueue(Q);
        printf("队长为%d\n", QueueLength(Q));
        GetHead(Q);
        PrintQueue(Q);
    }
    //初始化------------------------------------------------------
    void InitQueue(SqQueue &Q)
    {
        Q.base = new int[MAXSIZE];//为队列分配一个空间为MAXSIZE的数组空间
        Q.front = Q.rear = 0;  //初始化头、尾指针
    }
    //入队------------------------------------------------------
    void EnterQueue(SqQueue & Q, int e)
    {
        if ((Q.rear + 1) % MAXSIZE == Q.front) {
            
            printf("队列已满!\n");
            
        }
        Q.base[Q.rear] = e;    //将数组下标为尾指针的位置 添加入队元素e
        Q.rear = (Q.rear + 1) % MAXSIZE;
    }
    //出队------------------------------------------------------
    void OutQueue(SqQueue &Q) 
    {
        if (Q.front==Q.rear)
        {
            printf("该队列为空!\n");
        }
        int temp = Q.base[Q.front];//出队元素
        printf("出队元素为%d\n", temp);
        Q.front = (Q.front + 1) % MAXSIZE;//头指针向后移,完成出队

    }
    //取队头元素------------------------------------------------------
    void GetHead(SqQueue Q) 
    {
        if (Q.front != Q.rear) { //非空
            printf("队头元素为:%d\n", Q.base[Q.front]);
        }
    }
    //求队长度------------------------------------------------------
    int  QueueLength(SqQueue Q) 
    {
        int length = (Q.rear - Q.front + MAXSIZE) % MAXSIZE;
        return length;
    }
    //打印队------------------------------------------------------
    void PrintQueue(SqQueue Q) 
    {
        int temp = Q.front;
        printf("队中元素为:");
        while (temp != Q.rear) {  //未到队尾
            printf("%d  ", Q.base[temp]);
            temp++;
        }
    }

4.2链式队列

//链式队列的存储结构
typedef struct QNode  //定义节点
{
    int data;           //数据域
    struct QNode* next; //指针域
}QNode,*QueuePtr;
typedef struct 
{
    QueuePtr front;     //定义头指针
    QueuePtr rear;      //尾指针
}LinkQueue;

//初始化-链队列------------------------------------------------------
void InitQueue(LinkQueue &LQ) 
{
    LQ.front = LQ.rear = new QNode;  //生成一个新的节点,头、尾指针指向此节点;进来的元素直接用尾指针指向它,头指针不需要改变!
    LQ.front->next == NULL; //将头节点的指针域置为空
  //LQ.rear->next == NULL; //将头节点的指针域置为空
}

//入队------------------------------------------------------
void EnterQueue(LinkQueue &LQ, int data) 
{
    QueuePtr p = new QNode; //为入队元素分空间
    p->data = data;
    p->next = NULL;
    LQ.rear->next = p;  //队的尾指针指向该节点
    LQ.rear = p;        //尾指针后移
}

//出队------------------------------------------------------
void DepartQueue(LinkQueue& LQ) 
{
    if (LQ.front == LQ.rear) 
    {
        printf("队列为空!");
    }
    QueuePtr p = LQ.front->next;   //p指向队头元素
    int e = p->data;   //将出队元素赋给e
    LQ.front->next = p->next;//头指针后移
    printf("出队元素为:%d\n", e);
    delete(p);  //释放出队元素空间
}

//取队头元素------------------------------------------------------
void GetFront(LinkQueue LQ) 
{
    if (LQ.front != LQ.rear) {   //队列非空
        printf("%d\n", LQ.front->next->data);
    }
 }

//打印队列------------------------------------------------------
void PrintQueue(LinkQueue LQ) 
{
    QueuePtr temp = LQ.front;
    int e;
    while (temp != LQ.rear) {
        temp = temp->next;
        e = temp->data;
        printf("%d  ", e);
    }
    printf("\n");
}
//销毁队列------------------------------------------------------
void DestoryQueue(LinkQueue &LQ) 
{
    while (LQ.front) {
        LQ.front = LQ.rear = NULL;
        free(LQ.front);
        LQ.front = LQ.rear;
    }
}
//------------------------------------------------------
int main()
{
    LinkQueue LQ;
    InitQueue(LQ);
    EnterQueue(LQ, 1);
    EnterQueue(LQ, 2);
    EnterQueue(LQ, 3);
    EnterQueue(LQ, 4);
    EnterQueue(LQ, 5);
    PrintQueue(LQ);
    GetFront(LQ);//取队头元素
    DepartQueue(LQ);
    PrintQueue(LQ);
    DestoryQueue(LQ);
    PrintQueue(LQ);
}

你可能感兴趣的:(c语言,算法)