线性表
来源:互联网 发布:opencv lbp算法 编辑:程序博客网 时间:2024/05/16 04:20
线性表
6/27/2016 20:35 PM
1. 顺序线性表seqlist
在内存中的存储在连续的空间,可以利用一维数组实现。
特点:
1. 连续存储;2. 存取密度高;3. 删除、插入需要移动大量元素;4. 内存利用不灵活
2. 链式线性表linklist
内存中随机存储,分不再不同存储块,称为结点。通过指针相互链接。
typedef struct node_t{ data_t data; struct node_t* next; }linklist_t; //一般用typedef重名为linklist_t类型;
特点:
1.各个结点通过malloc动态分配空间;
2. 因此不是连续的;
相关功能实现代码
//在c语言中,非零==真#define TRUE 1#define FALSE 0typedef int data_t;typedef int bool;/*******节点类型定义Link_t*****/typedef struct node{ data_t data; //储存数据: struct node *next; //下一个节点指针域}Link_t;Link_t *linklist_create(); //创建链表bool linklist_isEmpty(Link_t *head); //判空//求链表长度,不包括头指针int linklist_getLength(Link_t *head); //求链表长度//找到指定位置pos的元素,这里人性化点,按照人思维,第1个就是head->next所指向data_t linklist_getElem(Link_t *head, int pos);//找到指定位置pos地址指针,同上,人性化Link_t* linklist_getLocation(Link_t *head, int pos);bool linklist_clear(Link_t *head); //清空void linklist_destroy(Link_t *head); //摧毁,释放内存空间bool linklist_insert(Link_t *head, int pos, data_t add); //在指定位置处插入元素,即前插,不是后插哦bool linklist_deletPosition(Link_t *head, int pos); //删除指定位置的元素bool linklist_deletElem(Link_t *head, data_t elem); //删除指定的元素int linklist_locate(Link_t *head, data_t elem); //定位elem在链表中第一次出现的位置bool linklist_dataReplace(Link_t * head, data_t old_data, data_t new_data); //将链表中old_data替换成new_databool linklist_showList(Link_t *head); //显示整个链表Link_t* linklist_malloc(); //为临时节点开辟空间void linklist_invert(Link_t *head); //链表倒置void linklist_sort(Link_t *head); //链表插入排序法#endif
/*linklist.c*/#include<stdio.h>#include<stdlib.h>#include <strings.h>#include "linklist.h"/*动态分配内存创建 *创建成功返回Link_t* 指针 * 失败:NULL */Link_t *linklist_create(){ Link_t *head = (Link_t *)linklist_malloc(); if(NULL == head) { printf("Linklist create Failed...\n"); return NULL; } bzero(head, sizeof(Link_t)); //将头指针初始化,假定-1为无效的数据,指针置空 head->data = -1; head->next = NULL; printf("new list has been created....\n"); return head;}bool linklist_isEmpty(Link_t * head){ return (head->next == NULL);}//求链表长度,不包括头指针int linklist_getLength(Link_t *head){ int len = 0; Link_t *p = head->next; while(NULL != p) { len++; p = p->next; } return len;}/* *清除链表 *不能过直接将头指针的next置空,否则链表其他的节点再也无法操作,导致内存一直占用 *除了头节点,其他节点空间全部释放 */bool linklist_clear(Link_t *head){ Link_t *p = head->next;//用于记录当前节点的下一个节点地址,方便循环 Link_t *q = NULL; //用于指向要删除的节点 while(NULL != p) { q = p; //将循环到的非空地址保存到q free(q); //释放q p = p->next; //p继续找到下一个 } head->next = NULL; //将头指针置空}data_t linklist_getElem(Link_t *head, int pos) //找到指定位置的元素{ //由于人性化,所以插入的位置不能为0,pos: [1,len+1] //插入的位置可以是最后一个元素的后边,因此<=len+1 if(pos < 1 || pos > linklist_getLength(head)+1) { printf("Position Invalid. Can`t find the elem...\n"); return FALSE; } int i = 0; Link_t *p = head->next; while(NULL != p) { i++; if(i == pos) { break; }else{ p = p->next; } } return p->data;}Link_t* linklist_getLocation(Link_t *head, int pos) //找到指定位置的地址{ if(pos < 1 || pos > linklist_getLength(head)+1) { printf("Position Invalid.GETLOCATION: Can`t find the elem...\n"); return NULL; } int i = 0; Link_t *p = head->next; while(NULL != p) { i++; if(i == pos-1) //找到指定位置的前一个即可通过p->next访问到pos处地址 { break; }else{ p = p->next; } } return p->next;}//找到指定位置pos的前一个节点,用于插入操作Link_t* linklist_preNode(Link_t *head, int pos){ //pos只能是从第一个到最后一个的下一个 if(pos < 1 || pos > linklist_getLength(head)+1) { printf("ERR: Position Invalid.Can`t find the elem before %d.\n", pos); return NULL; } int i = 0; //创建一个临时节点,默认先指向链表头节点 Link_t *p = head; /* * 错误在这里,由于只需要找到pos位置前的一个节点 * 因此只需要循环pos-1次 * 错在循环了pos次,从而超出了 */ for(i; i<pos-1; i++) { p = p->next; }// Link_t* p = linklist_getLocation(head, pos-1); //这里还是有问题!!!!!!!!!!!!!!!!! return p;}bool linklist_insert(Link_t *head, int pos, data_t add){ //判断插入的位置合法性,限定可插入的位置从第一个到最后一个的下一个[1,len+1] if(pos<1 || pos > (linklist_getLength(head)+1)) { printf("ERR: Position Invalid.\n"); return FALSE; } //找到要插入的位置的前一个节点 *pre Link_t *pre = linklist_preNode(head, pos); //这个函数出现了严重的错误,导致操作了非法内存 //开辟一个新的节点q来存放要插入的数据 Link_t *q = (Link_t*) malloc(sizeof(Link_t)); if(NULL == q) { printf("Insert: Malloc Failed....\n"); return FALSE; } bzero(q, sizeof(Link_t)); q->data = add; q->next = NULL; //插吧! q->next = pre->next; pre->next = q; return TRUE;}bool linklist_deletPosition(Link_t *head, int pos) //删除指定位置的元素{ //判断删除的位置合法性,限定可删除的位置从第一个到最后一个[1,len] if(pos<1 || pos > linklist_getLength(head)) { printf("Delet: Position Invalid.\n"); return FALSE; } /* *要删除pos处的元素 * 1.找到它前面的节点pre; * 2.将pre的指针域设为pos后的节点地址 * 3.释放pos处的节点 * */ Link_t *pre = linklist_preNode(head, pos); //第pos个前一个节点 Link_t *del = pre->next; //要删除的第pos个节点 pre->next = del->next; free(del); return TRUE;}bool linklist_deletElem(Link_t *head, data_t elem) //删除指定的元素{ Link_t *del = linklist_malloc(); if(NULL == del) { printf("ERR: DeletElem: malloc failed.\n"); return FALSE; } del->data = -1; del->next = NULL; int pos = 0; pos = linklist_locate(head, elem); linklist_deletPosition(head, pos);}int linklist_locate(Link_t *head, data_t elem) //定位elem在链表中第一次出现的位置,如果没找到,返回-1{ int pos = 0; Link_t *p = head->next; //遍历链表,找到指定元素的位置pos,然后调用linklist_deletPosition函数搞定 while(NULL != p) { pos++; if(p->data == elem) { return pos; } p = p->next; }}bool linklist_showList(Link_t *head){ if(head== NULL) { printf("链表空!\n"); return FALSE; } Link_t *p = head->next; while( NULL != p) { printf("%3d\n", p->data); p = p->next; } printf("\n"); return TRUE;}void linklist_destroy(Link_t *head){ //也可以先调用clear,然后在释放head即可 //遍历,依次释放各个节点内存 Link_t *p = head->next; Link_t *del = NULL; while(NULL != p) { del = p; p = p->next; free(del); } free(head);}bool linklist_dataReplace(Link_t * head, data_t old_data, data_t new_data) //将链表中old_data替换成new_data{ Link_t *p = head->next; while(old_data != p->data && p->next != NULL) { p = p->next; } //当找到old_data节点后,替换 p->data = new_data;/* //递归,直到全部替换 data_t older = old_data; data_t newer = new_data; linklist_dataReplace(p, older,newer);*/ return TRUE;}Link_t* linklist_malloc() //为临时节点开辟空间{ Link_t *p = (Link_t *) malloc(sizeof(Link_t)); if(NULL == p) { return NULL; } return p;}void linklist_invert(Link_t *head) //链表倒置{ //利用头插法 Link_t *p = head->next; //循环遍历指针 Link_t *t = p; //保存将要插入的节点 head->next = NULL;//**断开原链表** while(p != NULL) { t = p; //插入的是断开后的无头链表p的首节点 p = p->next; //p循环到下一个节点 /*这个操作不能和下面一条换位置,因为,现在t和p指向的是同一个节点, * 如果先执行下一步,那么相当于把p的next也改变了 * 但是先执行p = p->next,只是改变了指针变量p的指向地址,而t不会变*/ t->next =head->next; //继续把t封装好,记得把head当前的下一个节点地址保存到t->next中 head->next = t; }}void linklist_sort(Link_t *head) //链表插入排序法{ Link_t *p = head->next; //循环遍历指针 Link_t *t = head->next; //保存head后的有序链表 head->next = NULL;//断开原链表 //现将第一个元素直接插到head后边 head->next = p; p = p->next; while(p!= NULL) { if(p->data < t->data){ p->next = t; head->next = p; }else if(p->data > t->data){ if(t == NULL){ t->next = p; }else{ t = t->next; } } p = p->next; }}
0 0
- 线性表--线性存储
- 线性表 线性结构
- 线性表
- 线性表
- 线性表
- 线性表
- 线性表
- 线性表
- 线性表
- 线性表
- 线性表
- 线性表
- 线性表
- 线性表
- 线性表
- 线性表
- 线性表
- 线性表
- Android之ffmpeg-H264解码-移植ffmpeg中的H264解码部分到Android
- confluence(二)--破解
- java的关键字synchronized用法总结
- htk - lattice画图工具(plot lattice)
- 老曹骑士
- 线性表
- 剑指offer题解 连续子数组的最大和
- android开发之http协议
- JavaScript初了解
- iOS 数据持久化方式 - 归档 反归档
- Java异常处理和设计
- Spark,Hello World
- 框架 day65 Mybatis入门(基础知识:框架原理,入门[curd],开发dao层,全局与映射配置)
- 跟Google学写代码:Interacting with Other Apps【Capture Photo from phone】