数据结构学习笔记 (二)

来源:互联网 发布:涌金水利软件 编辑:程序博客网 时间:2024/05/04 00:21

线性表的链式表示和实现

单链表

链式结构的特点是用一组任意的存储元素来存储线性表的元素,在内存中可以是连续的也可以是不连续的。对于单链表来说,存储数据元素除了本身信息外(数据域),还要存储指示其直接后续的信息(指针域)。

struct Node{int data;Node *next;};class LinkList{Node *head;public:LinkList(){ head = new Node; head->next = NULL; };~LinkList(){ delete head; };void Create(int n);//创建长度为n的单链表int GetElem(int i);//获取第i个元素int Locate(int e);//返回第一个与e匹配的元素位序bool IsEmpty(){ return (head->next == NULL); }//判断是否为空表int Prior(int e);//e的前驱int Next(int e);//e的后续void Insert(int x, int i);//将x插入到i位置int Delete(int i);//删除表中第i个元素void Clear();//清空void Print();//输出};

结构体Node用来表示链表的每一个元素分别是数据域和它的指针域;

取元素

int LinkList::GetElem(int i){Node *p;int k, j;if (head->next == NULL){cout << "表为空" << endl;exit(0);}else{p = head;k = 0;while (p && k<i){p = p->next;k++;}if (!p||k>i){cout << "第" << i << "个元素不存在" << endl;exit(0);}return(p->data);}}

时间复杂度O(n);


插入操作

void LinkList::Insert(int x, int i){Node *p = head;int k = 0;while (p && k<i-1){p = p->next;k++;}if (!p||k>i-1){cout << "第" << i - 1 << "个元素不存在" << endl;exit(0);}Node *s = new Node;if (!s){cout << "空间分配失败" << endl;exit(0);}s->data = x;s->next = p->next;p->next = s;}

插入操作需要从链表的第一个节点开始根据后续的指针找到插入位置的前一个节点,然后把这个节点的后续指针指向新插入的节点,新插入的节点的后续指针则指向之前这个位置的节点。

删除操作

int LinkList::Delete(int i){Node *p = head;int k = 0;while (p&&k<i-1){p = p->next;k++;}if (!p||p->next==NULL){cout << "删除位置非法" << endl;exit(0);}Node *q = p->next;//暂存删除节点p->next = q->next;//删除int e = q->data;delete q;return e;}

删除操作也需要从第一个节点开始直到找到第i-1个节点,然后把i-1位置节点的后续指向i+1位置的节点,然后把第i位置的节点在内存中清除才能完成删除操作。

建立单链表

void LinkList::Create(int n){Node *p;for (int i = 0; i < n; i++){p = new Node;cin >> p->data;p->next = head->next;head->next == p;}}

双向链表

双向链表与单链表相比,最大的不同就是双向链表的元素不仅有数据和后续指针,它还有前驱的指针。通过一个节点不仅可以向前查找,也可以向后查找。

struct DNode{int data;DNode *prior;//前驱指针DNode *next;//后续指针};class DBList{DNode *head;public:DBList(){ head = new DNode; head->next = NULL; head->prior == NULL; };~DBList();void Create(int n);//创建长度为n的双链表int GetElem(int i);//取表中第i个元素DNode Locate(int e);//返回第一个与e匹配的节点指针bool IsEmpty();void Insert(int x, int i);int Delete(int i);void Clear();};

在双链表中,有些操作如取元素,求表长,定位等,只涉及一个方向的指针,则这些操作的算法描述和单链表相同。但在进行插入,删除操作时有很大的不同,在双链表中需同时修改两个方向上的指针,还要小心修改顺序。

双链表的节点删除操作

p -> prior -> next = p -> next;if(!p->next)p -> next -> prior = p -> prior;

双链表的节点插入操作

s = new DNode;s -> data = e;s -> prior = p -> prior;p -> prior = next = s;p -> prior = s;s -> next = p;

循环链表

循环链表是线性链表的一种变形,一般的链表结构最后一个节点的指针域为空,表示链表的结束。若使最后一个节点的指针指向头节点,则链表呈环状,称循环链表。


小结

链式存储结构特点:

优点:
1.节点空间的动态申请和动态释放,克服了顺序存储结构中需要预先设定数据元素的最大个数的缺点。
2.数据元素之间的次序是用指针来控制的,不像在顺序存储结构中进行插入,删除时需要移动大量数据元素。

缺点:
1.每个节点的指针域需要额外的存储空间,特别是当每个节点的数据域所占空间不是很大时,指针域所占空间就会显得很大。
2.链式存储结构是一种非随机存储结构,不能直接访问,从而增加了算法的时间复杂度。



0 0