• c语言提高学习笔记——03-c提高09day_数据结构


    在学习c语言提高-数据结构总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

    03-c提高09day_数据结构

    目录:
    1、单向链表
    练习1:单向链表(版本二)——(+初始化、+插入、+遍历)
    练习2:单向链表(版本二)——(+删除、+销毁)
     2、受限线性表——栈(Stack)
    (1)栈的基本概念
    (2)栈的顺序存储
    练习1:栈的顺序存储
    (3)栈的链式存储
    练习2:栈的链式存储
    (4)栈的应用(案例:就近匹配)
    练习:栈的应用:就近匹配

    1、单向链表

    (推荐版本二:代码少)

    练习1:单向链表(版本二)——(+初始化、+插入、+遍历)

    内存模型图如下:

     单向链表(版本二).c

      1 #define _CRT_SECURE_NO_WARNINGS
      2 #include<stdio.h>
      3 #include<string.h>
      4 #include<stdlib.h>
      5 
      6 //链表结点数据结构
      7 struct LinkNode
      8 {
      9     struct LinkNode* next;
     10 };
     11 
     12 //链表结构体
     13 struct LList
     14 {
     15     struct LinkNode header;//头结点给四个字节存地址
     16     int size;
     17 };
     18 
     19 typedef void* LinkList;
     20 
     21 //初始化链表
     22 LinkList Init_LinkList()
     23 {
     24     struct LList* list = malloc(sizeof(struct LList));
     25     if(NULL = list)
     26     {
     27         return NULL;
     28     }
     29     list->header.next = NULL;
     30     list->size = 0;
     31     
     32     return list;
     33 }
     34 //插入
     35 void Insert_LinkList(LinkList list, int position, void* data)
     36 {
     37     if(NULL = list)
     38     {
     39         return;
     40     }
     41     if(NULL = data)
     42     {
     43         return;
     44     }
     45     struct LList* mylist = (struct LList*)list;
     46     struct LinkNode* mynode = (struct LinNode*)data;
     47     
     48     if(position < 0 || position > mylist->size)
     49     {
     50         position = mylist->size;
     51     }
     52     
     53     //找位置(找到position位置的前一个位置)
     54     struct LinkNode* pCurrent = &(mylist->header);
     55     for(int i = 0; i < position; ++i)
     56     {
     57         pCurrent = pCurrent->next;
     58     }
     59     //数据入链表
     60     mynode->next = pCurrent->next;
     61     pCurrent->next = mynode;
     62     
     63     mylist->size++;
     64 }
     65 //遍历
     66 void Foreach_LinkList(LinkList list, void(*foreach)(void*))
     67 {
     68     if(NULL = list)
     69     {
     70         return;
     71     }
     72     if(NULL = foreach)
     73     {
     74         return;
     75     }
     76     
     77     struct LList* mylist = (struct LList*)list;
     78     struct LinkNode* pCurrent = &(mylist->header.next);
     79     
     80     while(pCurrent != NULL)
     81     {
     82         myforeach(pCurrent);
     83         pCurrent = pCurrent->next;
     84     }
     85     
     86 }
     87 
     88 struct Person
     89 {
     90     struct LinkNode node;//此处不能用指针,双链表会出问题,地址的位置
     91     char name[64];
     92     int age;
     93 };
     94 
     95 void myPrint(void* data)
     96 {
     97     struct Person* person = (struct Person*)data;
     98     printf("Name:%s Age:%d
    ", person->name, person->age);
     99 }
    100 
    101 void test()
    102 {
    103     //初始化链表
    104     LinkList list = Init_LinkList();
    105     //创建数据
    106     struct Person p1 = { NULL, "aaa", 10};
    107     struct Person p2 = { NULL, "bbb", 20};
    108     struct Person p3 = { NULL, "ccc", 30};
    109     struct Person p4 = { NULL, "ddd", 40};
    110     struct Person p5 = { NULL, "eee", 50};
    111     struct Person p6 = { NULL, "fff", 60};
    112     
    113     //插入数据
    114     Insert_LinkList(list, 0, &p1);
    115     Insert_LinkList(list, 0, &p2);
    116     Insert_LinkList(list, 0, &p3;
    117     Insert_LinkList(list, 0, &p4);
    118     Insert_LinkList(list, 0, &p5);
    119     Insert_LinkList(list, 0, &p6);
    120     
    121     //遍历
    122     Foreach_LinkList(list, myPrint);
    123 }
    124 
    125 int main(){
    126 
    127     test();
    128     
    129     system("pause");
    130     return EXIT_SUCCESS;
    131 }

    练习2:单向链表(版本二)——(+删除、+销毁)

      1 #define _CRT_SECURE_NO_WARNINGS
      2 #include<stdio.h>
      3 #include<string.h>
      4 #include<stdlib.h>
      5 
      6 //链表结点数据结构
      7 struct LinkNode
      8 {
      9     struct LinkNode* next;
     10 };
     11 
     12 //链表结构体
     13 struct LList
     14 {
     15     struct LinkNode header;//头结点给四个字节存地址
     16     int size;
     17 };
     18 
     19 typedef void* LinkList;
     20 
     21 //初始化链表
     22 LinkList Init_LinkList()
     23 {
     24     struct LList* list = malloc(sizeof(struct LList));
     25     if(NULL = list)
     26     {
     27         return NULL;
     28     }
     29     list->header.next = NULL;
     30     list->size = 0;
     31     
     32     return list;
     33 }
     34 //插入
     35 void Insert_LinkList(LinkList list, int position, void* data)
     36 {
     37     if(NULL = list)
     38     {
     39         return;
     40     }
     41     if(NULL = data)
     42     {
     43         return;
     44     }
     45     struct LList* mylist = (struct LList*)list;
     46     struct LinkNode* mynode = (struct LinNode*)data;
     47     
     48     if(position < 0 || position > mylist->size)
     49     {
     50         position = mylist->size;
     51     }
     52     
     53     //找位置(找到position位置的前一个位置)
     54     struct LinkNode* pCurrent = &(mylist->header);
     55     for(int i = 0; i < position; ++i)
     56     {
     57         pCurrent = pCurrent->next;
     58     }
     59     //数据入链表
     60     mynode->next = pCurrent->next;
     61     pCurrent->next = mynode;
     62     
     63     mylist->size++;
     64 }
     65 //遍历
     66 void Foreach_LinkList(LinkList list, void(*foreach)(void*))
     67 {
     68     if(NULL = list)
     69     {
     70         return;
     71     }
     72     if(NULL = foreach)
     73     {
     74         return;
     75     }
     76     
     77     struct LList* mylist = (struct LList*)list;
     78     struct LinkNode* pCurrent = &(mylist->header.next);
     79     
     80     while(pCurrent != NULL)
     81     {
     82         struct LinkNode* pNext = pCurrent->next;
     83         myforeach(pCurrent);
     84         pCurrent = pNext;
     85     }
     86     
     87 }
     88 
     89 //删除结点
     90 void RemoveByPos_LinkList(LinkList List, int position)
     91 {
     92     if(NULL == list)
     93     {
     94         return;
     95     }
     96     
     97     struct LList* mylist = (struct LList*)list;
     98     
     99     if(position < 0 || position > mylist->size - 1)
    100     {
    101         return;
    102     }
    103     
    104     //辅助指针
    105     struct LinkNode* pCurrent = &(mylist->header);
    106     for(int i = 0; i < position; ++i)
    107     {
    108         pCurrent = pCurrent->next;
    109     }
    110     
    111     //缓存下待删除结点
    112     struct LinkNode* pDel = pCurrent->next;
    113     
    114     //重新建立待删除结点的前驱和后继结点关系
    115     pCurrent->next = pDel->next;
    116     
    117     mylist->size--;
    118 }
    119 //销毁
    120 void Destroy_LinkList(LinkList list)
    121 {
    122     if(NULL == list)
    123     {
    124         return;
    125     }
    126     
    127     free(list);
    128     list = NULL;
    129 }
    130 
    131 struct Person
    132 {
    133     struct LinkNode node;//此处不能用指针,双链表会出问题,地址的位置!
    134     char name[64];
    135     int age;
    136 };
    137 
    138 void myPrint(void* data)
    139 {
    140     struct Person* person = (struct Person*)data;
    141     printf("Name:%s Age:%d
    ", person->name, person->age);
    142 }
    143 
    144 void test()
    145 {
    146     //初始化链表
    147     LinkList list = Init_LinkList();
    148     //创建数据(缺点:不能插入重复数据,会出问题!)
    149     struct Person p1 = { NULL, "aaa", 10};
    150     struct Person p2 = { NULL, "bbb", 20};
    151     struct Person p3 = { NULL, "ccc", 30};
    152     struct Person p4 = { NULL, "ddd", 40};
    153     struct Person p5 = { NULL, "eee", 50};
    154     struct Person p6 = { NULL, "fff", 60};
    155     
    156     //插入数据
    157     Insert_LinkList(list, 0, &p1);
    158     Insert_LinkList(list, 0, &p2);
    159     Insert_LinkList(list, 0, &p3;
    160     Insert_LinkList(list, 0, &p4);
    161     Insert_LinkList(list, 0, &p5);
    162     Insert_LinkList(list, 0, &p6);
    163     
    164     //遍历
    165     Foreach_LinkList(list, myPrint);
    166     
    167     //删除
    168     RemoveByPos_LinkList(list, 3);
    169     printf("---------------
    ");
    170     
    171     //遍历
    172     Foreach_LinkList(list, myPrint);
    173     
    174     //销毁
    175     Destroy_LinkList(list);
    176 }
    177 
    178 int main(){
    179 
    180     test();
    181     
    182     system("pause");
    183     return EXIT_SUCCESS;
    184 }

     2、受限线性表——栈(Stack)

    (1)栈的基本概念
    >概念:
    首先它是一个线性表,也就是说,栈元素具有线性关系,即前驱后继关系。只不过它是一种特殊的线性表而已。定义中说是在线性表的表尾进行插入和删除操作,这里表尾是指栈顶,而不是栈底。

    >特性
    它的特殊之处在于限制了这个线性表的插入和删除的位置,它始终只在栈顶进行。这也就使得:栈应是固定的,最先进栈的只能在栈底。(不支持随机存取)

    >操作
    ■栈的插入操作,叫做进栈,也称压栈。类似子弹入弹夹。
    ■栈的湖除操作,叫做出栈,也有的叫做猫栈,退栈。如同弹夹中的子弹出夹。

    (2)栈的顺序存储
    >基本概念
    栈的顺序存储结构简称顺序栈,它是运算受限制的顺序表。顺序栈的存储结构是:利用一组地址连续的的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针 top只是栈顶元素在顺序表中的位置。

    >设计与实现
    因为栈是一种特殊的线性表,所以栈的顺序存储可以通过顺序线性表来实现。

    练习1:栈的顺序存储

    栈的顺序存储.c

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<stdio.h>
     3 #include<string.h>
     4 #include<stdlib.h>
     5 #include"SeqStack.h"

    6 struct Person 7 { 8 char name[64]; 9 int age; 10 }; 11 12 void test() 13 { 14 //初始化栈 15 SeqStack stack = Init_SeqStack(); 16 17 //创建数据 18 struct Person p1 = { "aaa", 10}; 19 struct Person p2 = { "bbb", 20}; 20 struct Person p3 = { "ccc", 30}; 21 struct Person p4 = { "ddd", 40}; 22 struct Person p5 = { "eee", 50}; 23 struct Person p6 = { "fff", 60}; 24 25 //数据入栈 26 Push_SeqStack(stack, &p1); 27 Push_SeqStack(stack, &p2); 28 Push_SeqStack(stack, &p3); 29 Push_SeqStack(stack, &p4); 30 Push_SeqStack(stack, &p5); 31 Push_SeqStack(stack, &p6); 32 33 //输出栈中所有元素 34 while(Size_SeqStack(stack) > 0) 35 { 36 //获得栈顶元素 37 struct Person* person = (struct Person*)Top_SeqStack(stack); 38 //打印 39 printf("Name:%s Age:%d ", person->name, person->age); 40 //弹出栈顶元素 41 Pop_SeqStack(stack); 42 } 43 44 printf("Size:%d ", Size_SeqStack(stack)); 45 46 //销毁栈 47 Destroy_SeqStack(stack); 48 stack = NULL; 49 } 50 51 int main(){ 52 53 test(); 54 55 system("pause"); 56 return EXIT_SUCCESS; 57 }

    SeqStack.h

     1 #pragma once
     2 
     3 #include<stdlib.h>
     4 #include<string.h>//memset
     5 
     6 #ifdef __cplusplus
     7 extern "C"{
     8 #endif    
     9 
    10 
    11 #define MAX 1024
    12 
    13     //顺序栈数据结构
    14     struct SStack
    15     {
    16         void* data[MAX];//存放数据的数组
    17         int size;//栈中元素的个数
    18     }
    19     
    20     //数组高下标的位置当做栈顶,因为不需要移动数组中的元素在插入和删除中
    21     
    22     //初始化
    23     SeqStack Init_SeqStack();
    24     //入栈
    25     void Push_SeqStack(SeqStack stack, void* data);
    26     //出栈
    27     void Pop_SeqStack(SeqStack stack);
    28     //获得栈顶元素
    29     void* Top_SeqStack(SeqStack stack);
    30     //获得栈的大小
    31     int Size_SeqStack(SeqStack stack);
    32     //销毁栈
    33     void Destroy_SeqStack(SeqStack stack);
    34 
    35 #ifdef __cplusplus
    36 }
    37 #endif

    SeqStack.c

     1 #include"SeqStack.h"
     2 
     3 //初始化
     4 SeqStack Init_SeqStack()
     5 {
     6     struct SStack* stack = malloc(sizeof(struct SStack));
     7     if(NULL == stack)
     8     {
     9         return NULL;
    10     }
    11     
    12     memset(stack, 0, sizeof(struct SStack));
    13     stack->size = 0;
    14     
    15     return stack;
    16 }
    17 //入栈
    18 void Push_SeqStack(SeqStack stack, void* data)
    19 {
    20     if(NULL == stack)
    21     {
    22         return;
    23     }
    24     if(NULL == data)
    25     {
    26         return;
    27     }    
    28     
    29     struct SStack* s = (struct SStack*)stack;
    30     
    31     s->data[s->size] = data;
    32     s->size++;
    33 }
    34 //出栈
    35 void Pop_SeqStack(SeqStack stack)
    36 {
    37     if(NULL == stack)
    38     {
    39         return;
    40     }
    41     struct SStack* s = (struct SStack*)stack;
    42     
    43     if(s->size == 0)
    44     {
    45         return;
    46     }
    47     
    48     s->data[s->size-1] = NULL;//此句可有可无,有数据会把这块内存覆盖
    49     s->size--;
    50 }
    51 //获得栈顶元素
    52 void* Top_SeqStack(SeqStack stack)
    53 {
    54     if(NULL == stack)
    55     {
    56         return NULL;
    57     }
    58 
    59     struct SStack* s = (struct SStack*)stack;
    60     
    61     if(s->size == 0)
    62     {
    63         return NULL;
    64     }
    65     
    66     return s->data[s->size-1];
    67 }
    68 //获得栈的大小
    69 int Size_SeqStack(SeqStack stack)
    70 {
    71     if(NULL == stack)
    72     {
    73         return -1;
    74     }
    75 
    76     struct SStack* s = (struct SStack*)stack;
    77     return s->size;
    78 }
    79 //销毁栈
    80 void Destroy_SeqStack(SeqStack stack)
    81 {
    82     if(NULL == stack)
    83     {
    84         return;
    85     }
    86     free(stack);
    87         
    88 }


    (3)栈的链式存储

    >基本概念
    栈的链式存储结构简称链栈,

    练习2:栈的链式存储

    栈的链式存储.c

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<stdio.h>
     3 #include<string.h>
     4 #include<stdlib.h>
     5 #include"LinkStack.h"
    6 struct Person 7 { 8 struct StackNode node; 9 char name[64]; 10 int age; 11 }; 12 13 void test() 14 { 15 //初始化栈 16 LinkStack stack = Init_LinkStack(); 17 18 //创建数据 19 struct Person p1 = { NULL, "aaa", 10}; 20 struct Person p2 = { NULL, "bbb", 20}; 21 struct Person p3 = { NULL, "ccc", 30}; 22 struct Person p4 = { NULL, "ddd", 40}; 23 struct Person p5 = { NULL, "eee", 50}; 24 struct Person p6 = { NULL, "fff", 60}; 25 26 //数据入栈 27 Push_LinkStack(stack, &p1); 28 Push_LinkStack(stack, &p2); 29 Push_LinkStack(stack, &p3); 30 Push_LinkStack(stack, &p4); 31 Push_LinkStack(stack, &p5); 32 Push_LinkStack(stack, &p6); 33 34 //输出栈中所有元素 35 while(Size_LinkStack(stack) > 0) 36 { 37 //获得栈顶元素 38 struct Person* person = (struct Person*)Top_LinkStack(stack); 39 //打印 40 printf("Name:%s Age:%d ", person->name, person->age); 41 //弹出栈顶元素 42 Pop_LinkStack(stack); 43 } 44 45 printf("Size:%d ", Size_LinkStack(stack)); 46 47 //销毁栈 48 Destroy_LinkStack(stack); 49 stack = NULL; 50 } 51 52 int main(){ 53 54 test(); 55 56 system("pause"); 57 return EXIT_SUCCESS; 58 }

    LinkStack.h

     1 #pragma once
     2 
     3 #include<stdlib.h>
     4 
     5 #ifdef __cplusplus
     6 extern "C"{
     7 #endif    
     8 
     9 struct StackNode
    10 {
    11     struct StackNode* next;
    12 };
    13 
    14 struct LStack
    15 {
    16     struct StackNode header;//头结点,也可以没有
    17     int size;
    18 };
    19 
    20 typedef void* LinkStack;
    21 
    22     //初始化
    23     LinkStack Init_LinkStack();
    24     //入栈
    25     void Push_LinkStack(LinkStack stack, void* data);
    26     //出栈
    27     void Pop_LinkStack(LinkStack stack);
    28     //获得栈顶元素
    29     void* Top_LinkStack(LinkStack stack);
    30     //获得大小
    31     int Size_LinkStack(LinkStack stack);
    32     //销毁栈
    33     void Destroy_LinkStack(LinkStack stack);
    34 
    35 
    36 #ifdef __cplusplus
    37 }
    38 #endif

    LinkStack.c

     1 #include"LinkStack.h"
     2 
     3 //初始化
     4 LinkStack Init_LinkStack()
     5 {
     6     struct LStack* stack = malloc(sizeof(struct LStack));
     7     if(NULL == stack)
     8     {
     9         return NULL;
    10     }
    11     stack->header.next = NULL;
    12     stack->size = 0;
    13     
    14     return stack;
    15 }
    16 //入栈
    17 void Push_LinkStack(LinkStack stack, void* data)
    18 {
    19     if(NULL == stack)
    20     {
    21         return;
    22     }
    23     if(NULL == data)
    24     {
    25         return;
    26     }
    27     
    28     struct LStack* ls = (struct LStack*)stack;
    29     struct StackNode* node = (struct StackNode*)data;
    30     
    31     node->next = ls->header.next;//新结点的next指向ls的头结点的下一个结点
    32     ls->header.next = node;//ls头结点的下一个结点指向新结点
    33     
    34     ++(ls->size);
    35 }
    36 //出栈
    37 void Pop_LinkStack(LinkStack stack)
    38 {
    39     if(NULL == stack)
    40     {
    41         return;
    42     }
    43     
    44     struct LStack* ls = (struct LStack*)stack;
    45     
    46     if(ls->size == 0)
    47     {
    48         return;
    49     }
    50     
    51     //缓存第一个结点
    52     struct StackNode* pFirst = ls->header.next;
    53     
    54     ls->header.next = pFirst->next;
    55     
    56     ls->size--;
    57 }
    58 //获得栈顶元素
    59 void* Top_LinkStack(LinkStack stack)
    60 {
    61     if(NULL == stack)
    62     {
    63         return;
    64     }
    65     
    66     struct LStack* ls = (struct LStack*)stack;
    67     
    68     if(ls->size == 0)
    69     {
    70         return;
    71     }
    72     
    73     return ls->header.next;
    74 }
    75 //获得大小
    76 int Size_LinkStack(LinkStack stack)
    77 {
    78     if(NULL == stack)
    79     {
    80         return -1;
    81     }
    82 
    83     struct LStack* ls = (struct LStack*)stack;
    84     
    85     return ls->size;
    86 }
    87 //销毁栈
    88 void Destroy_LinkStack(LinkStack stack)
    89 {
    90     if(NULL == stack)
    91     {
    92         return;
    93     }
    94 
    95     free(stack);
    96     stack = NULL;
    97 }

    (4)栈的应用(案例:就近匹配)

    几乎所有的编译器都具有检测括号是否匹配的能力,那么如何实现编译器中的符号成对检测?如下字符串:
    5+5*(6)+9/3*1)-(1+3(

    >算法思路
    ■从第一个字符开始扫描
    ■当遇见普通字符时忽略,
    ■当遇见左符号时压入栈中
    ■当遇见右符号时从栈中弹出栈顶符号,并进行匹配
    ■匹配成功:继续读入下一个字符
    ■匹配失败:立即停止,并报错
    ■结束;
    ■成功;所有字符扫描完毕,且栈为空

    练习:栈的应用:就近匹配

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<stdio.h>
     3 #include<string.h>
     4 #include<stdlib.h>
     5 #include"SeqStack.h"
     6 
     7 int IsLeft(char ch)
     8 {
     9     return ch == "(";
    10 }
    11 
    12 int IsRight(char ch)
    13 {
    14     return ch == ")";
    15 }
    16 
    17 void printError(const char* str, char* errMsg, char *pos)
    18 {
    19     printError("错误信息:%s
    ", errMsg);
    20     printf("%s
    ", str);
    21     int dis = pos - str;
    22     for(int i = 0; i < dis; ++i)
    23     {
    24         printf(" ");
    25     }
    26     printf("A
    ");
    27 }
    28 
    29 void test()
    30 {
    31     const char* str = "5+5*(6)+9/3*1)-(1+3(";
    32     char* p = (char*)str;
    33     
    34     //初始化栈
    35     SeqStack stack = Init_SeqStack();
    36     
    37     while(*p != '')
    38     {
    39         //判断当前字符是否是左括号
    40         if(IsLeft(*p))
    41         {
    42             Push_SeqStack(stack, p);
    43         }
    44         //判断当前字符是否是右括号
    45         if(IsRight(*p))
    46         {
    47             if(Size_SeqStack(stack) > 0)
    48             {
    49                 //弹出栈顶元素
    50                 Pop_SeqStack(stack);
    51             }
    52             else
    53             {
    54                 printError(str, "右括号没有匹配的左括号!", p);
    55             }
    56         }        
    57         
    58         p++;
    59     }
    60     while(Size_SeqStack(stack) > 0)
    61     {
    62         printError(str, "没有匹配的右括号!", Top_SeqStack(stack));
    63         //弹出栈顶元素
    64         Pop_SeqStack(stack);
    65     }
    66     
    67     //销毁栈
    68     Destroy_SeqStack(stack);
    69     stack = NULL;
    70 }
    71 
    72 int main(){
    73 
    74     test();
    75     
    76     system("pause");
    77     return EXIT_SUCCESS;
    78 }

    在学习c语言提高-数据结构总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

  • 相关阅读:
    献给所有学习控件和组件开发的读者
    ASP.NET 2.0书稿最新进展——开始一审
    愿我们共同进步——献给《Programming ASP.NET 3rd. 中文版》
    Error from MSDN——No4. Login.UserName
    安装MSDN中文版后的乱弹
    Error from MSDN——No9. Login.UserNameRequiredErrorMessage
    Error from MSDN——No1. Roles.Enabled
    Error from MSDN——No8. Login.PasswordRequiredErrorMessage
    热心的朋友请注意:ASP.NET 2.0书稿目录征求意见
    撰写《ASP.NET 2.0开发指南》的非正式小结
  • 原文地址:https://www.cnblogs.com/Alliswell-WP/p/C_ImprovedLearning_09.html
Copyright © 2020-2023  润新知