线性表数据结构类型定义及相关操作总结

来源:互联网 发布:ecjia 源码破解 编辑:程序博客网 时间:2024/04/29 20:04

1、顺序存储结构(如数组)

定义:

#define MAXSIZE 20typedef struct{int data[MAXSIZE]; //假设这里是整型int length;  //线性表长度};

读取其中某个元素:假设线性顺序表已存在,读取其中第i个元素,其值返回到e中

#define ERROR 0#define OK 1   //定义返回状态int GetElem(Squlist L, int i, int *e){if (L.length == 0 || i<1 || i>L.length)  //该元素不存在或者超出表范围或者表为空则读取失败return ERROR;*e = L.data[i - 1];return OK;  //读取成功};
插入操作:在第i个元素前面插入元素e

int ListInsert(Squlist *L, int i, int e){int k;if (L->length == MAXSIZE) //表格是否满return ERROR;if (i<1 ||i>length+1)  //插入i不在范围内return ERROR;if (i <= L->length){for (k = length - 1; k >= i - 1; k--) L->data[k + 1] = L->data[k];}   L->data[i] = e;           length++;   return OK;};
删除操作:删除第i个元素并返回其值e

int ListDelete(Squlist *L, int i, int *e){int k;if (L->length == 0)      //表格为空return ERROR;if (i<1 || i>L->length)  //删除位置不正确return ERROR;if (i <= L->length){*e = L->data[i - 1];for (k = i; k < L->length - 1;k++)L->data[i - 1] = L->data[i];L->length--;return OK;}}

总结特点:查询元素方便(时间复杂度O(1)),插入和删除元素复杂(时间复杂度O(n))


2、链式存储结构(链表)
单链表的定义:

typedef struct Node {         //定义链表中的节点int data; //假设数据为整型struct Node *next;};typedef struct Node  *Linklist;  //定义一个链表类型的指针
链表读取:读取第i个数,其值返回e中

#define ERROR 0;#define OK  1;int GetElem(Linklist L, int i, int *e){int j=1;Linklist p;p = L->next;   //表示p指向了L->next,理解这点很重要while (p && j < 1){p = p->next;j++;}if (!p || j > i)return ERROR; &e = p->data;return OK;}

链表整表创建:头插法

void CreatLinklist(Linklist L, int n){Linklist p;int i;srand(time(0)); //初始化随机数种子L = (Linklist)malloc(sizeof(Node));L->next = NULL;     //建立带头结点的链表for (i = 0; i < n; i++){p = (Linklist)malloc(sizeof(Node));p->data = rand() % 100 + 1;//随机生成100以内的数字p->next = L->next;(->next = p;       //插入到表头}}
链表的插入:在第i个元素前面插入元素e

int LinklistInsert(LinkList L, int i, int e){int j;Linklist s, p;p = L;while (p && j < i){     //先找到插入的位置p = p->next;j++;}if (!p || j > i)return ERROR;s = (Linklist)malloc(sizeof(Node));s->data = e;s->next = p->next;     //插入链表s到p的后继p->next = s;return OK;}

链表的删除:删除第i个元素,返回其值到e中

int LinklistDelete(Linklist L, inti, int *e){int j = 1;Linklist p, q;p = L;while (p && j < i){p = p->next;j++;}if (!(p->next) || j > i)return ERROR;q = p->next;p->next = q->next;     //将q的后继赋值给p*e = q->data;free(q);              //系统回收此节点,释放内存return OK;}
整个链表的删除:

int CleatLinklist(Linklist L){Linklist p, q;p = L->next;while (p){q = p->next;free(q);p=q}L->next = NULL;    //头结点指针域为空return OK;}


总结链表的特点,可以看到每次读取一个数的时候,都要从表头一直读下去,复杂度为O(n),但是插入和删除时,找到特定位置后,再执行的时间复杂度为O(1)

3、循环链表

把单链表的终端节点指针域指向头结点,就形成了循环链表,可方便进行链表全部结点的遍历。判断的方法就是看p->next是否为头结点来结束循环


4、双向链表

和单向链表区别仅在于多了一个prior指针指向前面的结点,因此插入和删除操作也就多了几个关于prior的步骤

定义

typedef struct Node {         //定义链表中的节点int data; //假设数据为整型struct Node *next;struct Node *prior;};

单链表翻转

思路是每次翻转链表,把原始链表的第一个元素后面的那个元素放到表头

LinkList ReverseLinkedList(LinkList L){    Node   *first = NULL;  //指向原始链表最开始的第一个数据    Node   *behind = NULL; //每次新生成链表时,指向原始链表最开始的第一个数据的下一个数据     if (L == NULL)    {        return NULL;    }    first = L->next;    while (first->next != NULL)    {        behind = first->next;        first->next = behind->next;        behind->next = L->next;        L->next = behind;    }    return L;}








0 0
原创粉丝点击