1.动态创建(简)
思路:
①先创建结构体,再创建结构体数组,为了方便以后修改,可以取一些别名;
②如果没有创建成功,那么要及时销毁之前所创建的堆区,防止内存泄漏;
③编写插入数据函数时需要考虑头插还是尾插,亦或者中间插入;
④编写删除函数时要考虑多个相同数据位于一堆怎么删除,连续数据位于末尾怎么删除,这里要注意越界问题;
⑤考虑是否需要用到二级指针更改实参,只更改形参是否可以达到目的;
⑥如有错误,可以用跟踪打印或者jdb调试来查找错误,例如:
132 printf("%d %s %s\n",__LINE__,__FILE__,__FUNCTIO N__); root@ubuntu:/mnt/U_share/DATA# ./a.out 132 seqlist.c main //运行到这里表示没错,机器思想
root@ubuntu:/mnt/U_share/DATA# gcc seqlist.c root@ubuntu:/mnt/U_share/DATA# ./a.out please input increase data:1 please input increase data:1 please input increase data:2 please input increase data:2 please input increase data:3 please input increase data:4 please input increase data:4 please input increase data:q 4 4 3 2 2 1 1 please input delete data:1 please input delete data:q 4 4 3 2 2 please input change pos and data:0,5 5 4 3 2 2 the select*from:3 data:5
1 /*=============================================== 2 * 文件名称:seqlist.c 3 * 创 建 者: 4 * 创建日期:2022年07月05日 5 * 描 述: 6 ================================================*/ 7 #include <stdio.h> 8 #include <stdlib.h>//malloc(),free() 9 typedef int type;//便于更改类型,char... 10 typedef struct data{ 11 type *data;//存放数组的首地址 12 int len;//存放数组下标的长度 13 int maxlen;//存放数组的最大长度 14 }List,*pList;//*pList是定义的结构体指针,简化代码的编写 15 //声明顺序表初始化函数(根据返回值,弊端:返回数据为-1) 16 pList list_create(int maxlen) 17 { 18 //开辟顺序表 19 //List *p = malloc(List); 20 pList p = malloc(sizeof(List)); 21 if(NULL==p){ 22 perror("malloc_list"); 23 return NULL; 24 } 25 //开辟顺序表内部数组 26 p->data = malloc(maxlen*sizeof(type)); 27 if(NULL==p->data){ 28 perror("malloc_data"); 29 free(p);//开辟数组失败,释放结构体指针 30 return NULL; 31 } 32 p->maxlen = maxlen; 33 p->len = -1;//对应数组下标,也可以从0开始 34 return p; 35 } 36 //声明插入数据函数 37 int list_insert_pos(pList L,int pos,int data) 38 { 39 if(NULL==L)//判断顺序表L是否已经被创建 40 return -1; 41 //判满以及插入下标是否有效 42 if(L->len==L->maxlen || pos<0 || pos>L->len+1){ 43 fputs("error",stdout); 44 return -1; 45 } 46 L->len++;//下标加1,然后插入元素 47 //从最后一个元素依次右移,2插入位置停止 48 for(int i=L->len;i>pos;i--) 49 L->data[i] = L->data[i-1]; 50 L->data[pos] = data; 51 return 0; 52 } 53 //声明插入释放函数 54 int list_free(pList *L) 55 { 56 if(NULL==*L) 57 return -1; 58 free((*L)->data);//释放结构体内部 59 free(*L);//释放顺序表 60 *L = NULL;//将指针指向空,防止隐患 61 return 0; 62 } 63 //声明判满函数 64 int list_full(pList L) 65 { 66 if(NULL==L) 67 return -1; 68 if(L->len == L->maxlen) 69 return 0; 70 return -1; 71 } 72 //声明判空函数 73 int list_empty(pList L) 74 { 75 if(NULL==L) 76 return -1; 77 if(-1 == L->len) 78 return 0; 79 return -1; 80 } 81 //声明更改函数 82 int list_change_pos(pList L,int pos,int data) 83 { 84 if(NULL==L || 0==list_empty(L)) 85 return -1; 86 if(pos<0 || pos > L->len) 87 return -1; 88 L->data[pos] = data; 89 return 0; 90 } 91 //声明查询函数 92 int list_select_pos(pList L,int pos,int *data) 93 { 94 if(NULL==L || 0==list_empty(L)) 95 return -1; 96 for(int i=0;i<=L->len;i++){ 97 if(i == pos) 98 printf("the select*from:%d\n",L->data[i]); 99 } 100 return 0; 101 102 } 103 //删除元素 104 int list_delete_data(pList L,int data) 105 { 106 if(NULL==L || 0==list_empty(L)) 107 return -1; 108 int i=0,j; 109 while(i <= L->len){ 110 if(data == L->data[i]){ 111 j=i;//;为了连续删除做个标志位 112 while(j < L->len){ 113 L->data[j] = L->data[j+1]; 114 j++; 115 } 116 L->len--; 117 //为了不被遗漏元素,数组下标减1,例如偶数次元素只删除一个 118 i--; 119 } 120 i++; 121 } 122 return 0; 123 } 124 int list_insert_pos(pList L,int pos,int data); 125 int list_delete_data(pList L,int data); 126 int list_change_pos(pList L,int pos,int data); 127 int list_select_pos(pList L,int pos,int *data); 128 int main(int argc,char argv[]) 129 { 130 pList p = list_create(10); 131 type data;//上文区别名 int 132 while(1){ 133 printf("please input increase data:"); 134 if(0 == scanf("%d",&data)){ 135 getchar(); 136 break; 137 } 138 list_insert_pos(p,0,data);//头插 139 } 140 for(int i=0;i<=p->len;i++) 141 printf("%d ",p->data[i]); 142 puts(""); 143 while(1){ 144 printf("please input delete data:"); 145 if(0 == scanf("%d",&data)){ 146 getchar(); 147 break;//输入字母退出 148 } 149 list_delete_data(p,data); 150 } 151 for(int i=0;i<=p->len;i++) 152 printf("%d ",p->data[i]); 153 puts(""); 154 type j; 155 fputs("please input change pos and data:",stdout); 156 scanf("%d,%d",&j,&data); 157 list_change_pos(p,j,data); 158 for(int i=0;i<=p->len;i++) 159 printf("%d ",p->data[i]); 160 puts(""); 161 list_select_pos(p,2,&data); 162 printf("data:%d\n",data); 163 return 0; 164 }
2.动态创建(繁、待改进)
#include <stdio.h> #include <stdlib.h> typedef int type; typedef struct data{ type *data; int len; int maxlen; }Seqlist,*pSeqlist; //创建并初始化顺序表(根据参数返回) int list_create(pSeqlist *L,int len) { (*L) = malloc(sizeof(Seqlist)); // pSeqlist p = malloc(sizeof(Seqlist)); // 注意:返回值返回和参数返回是不一样的,返回值返回需要定义一个指针,然后会返回指针,而参数返回是以及定义好了指针只需要传就行了 if(NULL == *L){ perror("list_malloc"); return -1;//-1或者NULL根据参数或返回值判断 } (*L)->data = malloc(len*sizeof(type)); if(NULL == (*L)->data){ perror("data_malloc"); free(*L); *L = NULL; return -1; } (*L)->len = -1; return 0; } //顺序表判空 int list_empty(pSeqlist L) { if(NULL == L) return -1; if(-1 == L->len) return -1; return 0; } //顺序表判满 int list_full(pSeqlist L) { if(NULL == L) return -1; if(L->len+1 == L->maxlen)//结构体成员变量的引用 return 0; return -1; } //顺序表按位置插入元素 int list_insert_pos(pSeqlist L,int pos,type data) { if(NULL == L || 0 == list_full(L)) return -1; if(-1>pos || L->len<pos) return -1; L->len++; for(int i=L->len;i>pos;i--)//先遍历到pos处 L->data[i] = L->data[i-1]; L->data[pos] = data; return 0; } //顺序表删除元素 int list_delete(pSeqlist L,type data) { if(NULL==L || 0==list_empty(L)) return -1; for(int i=0;i<=L->len;i++){//下标取等 if(data == L->data[i]){ for(int j=i;j<L->len;j++)//越界不取等 L->data[j] = L->data[j+1];//j+1 //那么问题来了,最后一个元素是需要删除的元素呢? //这一步的另一个作用,如果最后一个元素需要被删除直接顺序表长度减1 L->len--; //为了能连续删除相同的元素,因为后面有个i++,如果不执行这一步,那么第一个需要删除元素被第二个连续需要删除元素替换后,第二个连续连续删除元素便漏了,比如1 2 2 3 i--; } } return 0; } //顺序表展现元素 int list_show(pSeqlist L) { if(NULL==L || 0==list_empty(L)){ perror("s"); return -1; } for(int i=0;i<=L->len;i++) printf("%d ",L->len); printf("%d,%s,%s\n",__LINE__,__FILE__,__FUNCTION__); puts(""); return 0; } //顺序表按位置修改元素 int list_change_pos(pSeqlist L,int pos,type data) { if(NULL==L || 0==list_empty(L)) return -1; int i=0; while(i<=L->len){ L->data[pos] = data; i++; } return 0; } //顺序表查询指定元素 int list_watch_pos(pSeqlist L,int pos,type *data) { if(NULL==L || 0==list_empty(L)) return -1; if(-1>pos || pos<L->len) return -1; for(int i=0;i<L->len;i++){ if(i==pos) printf("the select:%d\n",L->data[i]); } return 0; } //释放顺序表 int list_destory(pSeqlist *L) { if(NULL == *L) return -1; free((*L)->data); free(*L); return 0; } int list_create(pSeqlist *L,int len); int list_empty(pSeqlist L); int list_full(pSeqlist L); int list_insert_pos(pSeqlist L,int pos,type data); int list_delete(pSeqlist L,type data); int list_show(pSeqlist L); int list_change_pos(pSeqlist L,int pos,type data); int list_watch_pos(pSeqlist L,int pos,type *data); int main(int argc, char *argv[]) { type data,loc; pSeqlist p = NULL; list_create(&p,10); while(1){ printf("please input insert data:"); if(0 == scanf("%d",&data)){ getchar(); break; } list_insert_pos(p,0,data); } //有误,调用不了list_show()函数 //list_show(p); for(int i=0;i<=p->len;i++) printf("%d ",p->data[i]); puts(""); while(1){ printf("please input additive loc and data:"); if(0 == scanf("%d,%d ",&loc,&data)){ getchar(); break; } list_insert_pos(p,loc,data); } list_change_pos(p,3,7); list_show(p); while(1){ printf("please input delete data:"); if(0 == scanf("%d ",&data)){ getchar(); break; } list_delete(p,data); } list_show(p); printf("please input select data:\n"); scanf("%d",&data); list_watch_pos(p,2,&data); list_show(p); list_destory(&p); if(NULL == p) fputs("this is NULL.",stdout); return 0; }
3.静态创建
#include <stdio.h> #define Max 10; typedef struct{ int data[Max]; int len; }Seqlist,*pSeqlist;
顺序表的特点:
- 随机访问 ,时间复杂度为O(1)时间。
- 存储密度高。
- 拓展容量不方便。
- 插入、删除操作不方便,需要移动大量元素。
<>指定根目录
""当前目录或指定目录
1.数据:信息的载体。
2.数据元素:数据的基本单位,又叫记录。
3.数据结构:数据元素及数据元素之间的相互关系,或组织数据的形式。
4.数据结构的概念:
逻辑结构:数据运算之间的抽象关系(邻接,从属)。
线性结构、非线性结构
存储结构:逻辑结构在计算机中的具体实现方法。
5.顺序存储方法、链式存储方法、索引存储方法、散列存储方法
6.数据运算:对数据进行的操作。
插入、删除、修改、查找、排序等。数据的四种存储结构:
顺序存储结构:借助元素在存储器中的相对位置来表示逻辑关系
链式存储结构:存储指针的位置
索引存储
散列存储7.线性结构:线性表、栈、队
非线性结构:树、图
存储:顺序、链式8.算法:一个有穷规则(语句、指令)的有序集合。
9.算法的特性:有穷性、确定性、可行性、输入、输出
有穷性:算法执行的步骤或规则是有限的。
确定性:每个计算步骤无二义性。
可行性:每个计算步骤能够在有限的时间内完成。
输入 :算法有零个或者多个外部输入。
输出 :算法有一个或者多个输出。10.算法分析:在算法正确的前提下,评价算法的好坏。
时间复杂度
空间复杂度 这两者结合为时空复杂度
容易理解、容易编程和调试、容易维护
11.问题规模数据结构+算法=程序
好的算法:
算法对应的程序所耗时间少;
算法对应的程序所耗存储空间少;
算法结构性好,易读、易移植和调试等等。12.语句的频度:在程序中重复执行的次数。
举例:冒泡排序法的时间复杂度。T(n)=n(n-1)
T(n)的量级:
O(c)、O(n)、O(n2)、O(n3)、
对数级O(log2n)、
线性对数级O(n*log2n)、
指数级O(2n),时间复杂度最差