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\n", 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\n", 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("---------------\n");
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\n", person->name, person->age); 40 //弹出栈顶元素 41 Pop_SeqStack(stack); 42 } 43 44 printf("Size:%d\n", 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\n", person->name, person->age); 41 //弹出栈顶元素 42 Pop_LinkStack(stack); 43 } 44 45 printf("Size:%d\n", 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\n", errMsg);
20     printf("%s\n", str);
21     int dis = pos - str;
22     for(int i = 0; i < dis; ++i)
23     {
24         printf(" ");
25     }
26     printf("A\n");
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 != '\0')
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,转载请注明出处。

posted on 2020-06-09 18:18  Alliswell_WP  阅读(172)  评论(0编辑  收藏  举报

导航