线性表

来源:互联网 发布:opencv lbp算法 编辑:程序博客网 时间:2024/05/16 04:20

线性表

6/27/2016 20:35 PM

1. 顺序线性表seqlist

在内存中的存储在连续的空间,可以利用一维数组实现。

特点:

1.  连续存储;2.  存取密度高;3.  删除、插入需要移动大量元素;4.  内存利用不灵活

内存中随机存储,分不再不同存储块,称为结点。通过指针相互链接。

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