次序表和链表知识点

打印 上一主题 下一主题

主题 529|帖子 529|积分 1587

1 次序表

   次序表是指用一段物理所在一连的空间去存储数据的线性布局。
  次序表有两种:静态次序表,动态次序表。
  

  1.1 静态次序表布局体定义

  1. typedef int ElemDataSL;
  2. typedef struct SequeList {
  3.         ElemDataSL arr[100];
  4.         int size;
  5. }SL;
复制代码
  静态次序表在创建布局体的时候就已经把容量固定,后期空间不敷,不允许增长新空间,以是并不方便实际使用。
  例子:通讯录(C语言实现)-CSDN博客
1.2 动态次序表布局体定义

  1. typedef int ElemDataSL;
  2. typedef struct SequeList {
  3.         ElemDataSL* arr;
  4.         int size;
  5.         int capatity;
  6. }SL;
复制代码
   动态次序表在创建布局体的时候定义了arr的指针作为一段一连内存空间的首所在,如果有需要可以用realloc开辟新空间进行扩容处理。
  1.2.1 接口声明

  1. //初始化
  2. void InitSequeList(SL* s);
  3. //尾插
  4. void SequeListPushBack(SL* s,ElemDataSL num);
  5. //尾删
  6. void SequeListPopBack(SL* s);
  7. //头插
  8. void SequeListPushFront(SL* s, ElemDataSL num);
  9. //头删
  10. void SequeListPopFront(SL* s);
  11. //pos处插
  12. void SequeListPushInsert(SL* s,ElemDataSL num,int pos);
  13. //pos处删
  14. void SequeListPopInsert(SL* s,int pos);
  15. //显示
  16. void SequeListShowData(SL* s);
  17. // 顺序表删除pos位置的值
  18. void SequeListErase(SL*s, size_t pos);
  19. // 顺序表销毁
  20. void SequeListDestory(SL* s);
复制代码
1.2.2 初始化

  1. //初始化
  2. void InitSequeList(SL* s) {
  3.         assert(s);
  4.         s->arr = (ElemDataSL*)malloc(DefaultData * sizeof(ElemDataSL));
  5.         s->capatity = DefaultData;
  6.         s->size = 0;
  7. }
复制代码
1.2.3 尾插

  1. //尾插
  2. void SequeListPushBack(SL* s,ElemDataSL num) {
  3.         assert(s);
  4.         AddCapatity(s);
  5.         s->arr[s->size] = num;
  6.         s->size++;
  7. }
复制代码
 1.2.4 尾删

  1. //尾删
  2. void SequeListPopBack(SL* s)
  3. {
  4.     assert(s);
  5.         s->size--;
  6. }
复制代码
1.2.5 头插

  1. //头插
  2. void SequeListPushFront(SL* s,ElemDataSL num) {
  3.         AddCapatity(s);
  4.         for (int i = s->size-1; i >=0; i--)
  5.         {
  6.                 s->arr[i + 1] = s->arr[i];
  7.         }
  8.         s->arr[0] = num;
  9.         s->size++;
  10. }
复制代码
1.2.6 头删

  1. //头删
  2. void SequeListPopFront(SL* s)
  3. {
  4.         for (int i = 0; i <= s->size - 1; i++)
  5.         {
  6.                 s->arr[i] = s->arr[i + 1];
  7.         }
  8.         s->size--;
  9. }
复制代码
1.2.7 中间插入

  1. //pos处插
  2. void SequeListPushInsert(SL* s,ElemDataSL num,int pos)
  3. {
  4.         AddCapatity(s);
  5.         for (int i = s->size - 1; i >= pos-1; i--)
  6.         {
  7.                 s->arr[i + 1] = s->arr[i];
  8.         }
  9.         s->arr[pos-1] = num;
  10.         s->size++;
  11. }
复制代码
1.2.8 中间删除

  1. //pos处删
  2. void SequeListPopInsert(SL* s, int pos) {
  3.         for (int i = pos-1; i <= s->size - 1; i++)
  4.         {
  5.                 s->arr[i] = s->arr[i + 1];
  6.         }
  7.         s->size--;
  8. }
复制代码
1.2.9 打印次序表

  1. //显示
  2. void SequeListShowData(SL* s)
  3. {
  4.         assert(s);
  5.         for (int i = 0; i < s->size; i++)
  6.         {
  7.                 printf("%d ", s->arr[i]);
  8.         }
  9.         printf("\n");
  10. }
复制代码
1.3 次序表烧毁

  1. // 顺序表销毁
  2. void SequeListDestory(SL* s) {
  3.         free(s->arr);
  4.         s->arr = NULL;
  5. }
复制代码
  次序表优点:可以使用随机访问。
  缺点:开辟空间可能会导致空间浪费,增删改查的时间复杂度为O(N)。
  2 链表

   链表是一种物理存储布局上非一连、非次序的存储布局,数据元素的逻辑次序是通过链表中的指针链接次序实现的 。
  

  留意:
  1、链式布局在逻辑上是一连的,但在物理上非一连。
  2、在堆上开辟空间。
  3、在堆上申请空间,按照一定战略进行的,两次开辟的空间可能一连也可能不一连。
  2.1 单链表


   无头单向非循环链表:布局简单,一般不会单独用来存数据。实际中更多是作为其他数据布局的子布局,如哈希桶、图的邻接表等等。
  2.2 接口声明

  1. typedef int SLDATATYPE;
  2. typedef struct SListNode {
  3.         int data;
  4.         struct SListNode* next;
  5. }SListNode;
  6. //尾插
  7. void SListPushBack(SListNode** pphead, SLDATATYPE num);
  8. //尾删
  9. void SListPopBack(SListNode* phead);
  10. //头插
  11. void SListPushFront(SListNode** pphead, SLDATATYPE num);
  12. //头删
  13. void SListPopFront(SListNode* phead);
  14. //查找
  15. SListNode* SListFind(SListNode* phead, SLDATATYPE num);
  16. //中间后插
  17. void SListInsertAfter(SListNode* pos, SLDATATYPE num);
  18. //中间删
  19. void SListEraseAfter(SListNode* pos);
  20. //打印
  21. void SListPrint(SListNode* phead);
  22. //销毁链表
  23. void SListDistory(SListNode** phead);
复制代码
2.3 尾插

  1. //尾插
  2. void SListPushBack(SListNode* *pphead, SLDATATYPE num) {
  3.        
  4.         SListNode* NewNode = BuySListNode(num);
  5.         if (*pphead == NULL)
  6.         {
  7.                 *pphead= NewNode;
  8.         }
  9.         else
  10.         {        SListNode* tail = *pphead;
  11.                 while (tail->next!=NULL)
  12.                 {
  13.                         tail = tail->next;
  14.                 }
  15.                 tail->next= NewNode;
  16.         }
  17. }
复制代码
2.4 尾删

  1. //尾删
  2. void SListPopBack(SListNode** phead)
  3. {
  4.         SListNode* tail = *phead;
  5.         SListNode* prev = tail;
  6.         if (*phead == NULL)
  7.         {
  8.                 return;
  9.         }
  10.         else if ((*phead)->next == NULL)
  11.         {
  12.                 free(*phead);
  13.                 *phead = NULL;
  14.         }
  15.         else
  16.         {
  17.                 while (tail->next != NULL)
  18.                 {
  19.                         prev = tail;
  20.                         tail = tail->next;
  21.                 }
  22.                 free(tail);
  23.                 prev->next = NULL;
  24.         }
  25.        
  26. }
复制代码
2.5 头插

  1. //头插
  2. void SListPushFront(SListNode** pphead, SLDATATYPE num)
  3. {
  4.         SListNode* newNode = BuySListNode(num);
  5.         if ((*pphead) == NULL)
  6.         {
  7.                 *pphead = newNode;
  8.         }
  9.         else
  10.         {
  11.                 newNode->next = *pphead;
  12.         }
  13.         *pphead = newNode;
  14. }
复制代码
2.6 头删

  1. //头删
  2. void SListPopFront(SListNode* *pphead)
  3. {       
  4.         SListNode* head = *pphead;
  5.         if (head == NULL)
  6.         {
  7.                 return;
  8.         }
  9.         else if (head->next == NULL)
  10.         {
  11.                 *pphead = NULL;
  12.         }
  13.         else
  14.         {
  15.                 (*pphead) = (*pphead)->next;
  16.                 free(head);
  17.         }
  18.        
  19.        
  20. }
复制代码
2.7 查找

  1. SListNode* SListFind(SListNode* phead, SLDATATYPE num) {
  2.         SListNode* ptr = phead;
  3.         while (ptr)
  4.         {
  5.                 if (ptr->data == num)
  6.                 {
  7.                         printf("%d找到了!\n",ptr->data);
  8.                         return  ptr;
  9.                 }
  10.                 ptr = ptr->next;
  11.         }
  12.         printf("%d没找到!\n",num);
  13.         return NULL;
  14. }
复制代码
2.8 中间后插

  1. void SListInsertAfter(SListNode* *pos, SLDATATYPE num)
  2. {
  3.         SListNode* newNode = BuySListNode(num);
  4.         newNode->next = (*pos)->next;
  5.         (*pos)->next = newNode;
  6. }
复制代码
2.9 中间后删

  1. void SListEraseAfter(SListNode* pos)
  2. {
  3.         assert(pos);
  4.         assert(pos->next);
  5.         SListNode* next = pos->next;
  6.         pos->next = next->next;
  7.         free(next);
  8. }
复制代码
3 打印

  1. //打印
  2. void SListPrint(SListNode* phead)
  3. {
  4.         SListNode* cur = phead;
  5.         while (cur)
  6.         {
  7.                 printf("%d->", cur->data);
  8.                 cur = cur->next;
  9.         }
  10.         printf("NULL\n");
  11. }
复制代码
3.1 烧毁链表

  1. void SListDistory(SListNode** phead)
  2. {
  3.         assert(*phead);
  4.         SListNode* next = (*phead)->next;
  5.         while (next)
  6.         {
  7.                 free(*phead);
  8.                 *phead = next;
  9.                 next = next->next;
  10.         }
  11.         free(*phead);
  12.         *phead = NULL;
  13. }
复制代码
  单链表优点:需要增长多少个元素就开辟多少空间不会导致空间浪费,插入时间复杂度低。
  缺点:不能随机访问,只能依次往后访问,无法实现从后往前。
  2.2 双链表

   

  头节点不存储有效数据。
  2.2.1 接口声明

  1. typedef int ListData;
  2. typedef struct ListNode
  3. {
  4.         ListData data;
  5.         struct ListNode* next;
  6.         struct ListNode* prev;
  7. }ListNode;
  8. //链表创建
  9. ListNode* ListCreate();
  10. //尾插
  11. void ListPushBack(ListNode* phead, ListData x);
  12. //尾删
  13. void ListPopBack(ListNode* phead);
  14. //头插
  15. void ListPushFront(ListNode* phead, ListData x);
  16. //头删
  17. void ListPopFront(ListNode* phead);
  18. //查找
  19. ListNode* ListFind(ListNode* phead, ListData x);
  20. //中间插
  21. void ListInsert(ListNode* pos,ListData x);
  22. //中间删
  23. void ListErase(ListNode* pos);
  24. //显示
  25. void ListPrint(ListNode* phead);
  26. //清空链表
  27. void ListClear(ListNode** phead);
  28. //销毁链表
  29. void ListDestory(ListNode* phead);
复制代码
2.2.2 创建新节点 

  1. ListNode* BuyListNode(ListData x)
  2. {
  3.         ListNode* node = (ListNode*)malloc(sizeof(ListNode));
  4.         node->data = x;
  5.         node->next = NULL;
  6.         node->prev = NULL;
  7.         return node;
  8. }
复制代码
2.2.3 双链表创建

  1. ListNode* ListCreate() {
  2.         ListNode* phead = BuyListNode(0);
  3.         phead->next = phead;
  4.         phead->prev = phead;
  5.         return phead;
  6. }
复制代码
2.2.4 尾插 

  1. //尾插
  2. void ListPushBack(ListNode* phead, ListData x)
  3. {
  4.         assert(phead);
  5.         ListNode* tail = phead->prev;
  6.         ListNode* newNode = BuyListNode(x);
  7.         tail->next = newNode;
  8.         newNode->prev = tail;
  9.         newNode->next = phead;
  10.         phead->prev = newNode;
  11. }
复制代码
 2.2.5 尾删

  1. //尾删
  2. void ListPopBack(ListNode* phead)
  3. {
  4.         assert(phead->next != phead);
  5.         /*ListNode* tail = phead->prev;
  6.         ListNode* tailPrev = tail->prev;
  7.         tailPrev->next = phead;
  8.         phead->prev = tailPrev;*/
  9.         ListErase(phead->prev);
  10. }
复制代码
2.2.6 头插

  1. //头插
  2. void ListPushFront(ListNode* phead, ListData x)
  3. {
  4.         ListNode* newNode = BuyListNode(x);
  5.         ListNode* pheadNext = phead->next;
  6.         phead->next = newNode;
  7.         newNode->prev = phead;
  8.         newNode->next = pheadNext;
  9.         pheadNext->prev = newNode;
  10. }
复制代码
2.2.7 头删 

  1. //头删
  2. void ListPopFront(ListNode* phead)
  3. {
  4.         ListNode* pheadNext = phead->next;
  5.         phead->next = pheadNext->next;
  6.         pheadNext->next->prev = phead;
  7.         free(pheadNext);
  8. }
复制代码
2.2.8 查找

  1. //查找
  2. ListNode* ListFind(ListNode* phead, ListData x)
  3. {
  4.         ListNode* pos = NULL;
  5.         ListNode* cur = phead->next;
  6.         while (cur != phead)
  7.         {
  8.                 if (cur->data == x)
  9.                 {
  10.                         pos = cur;
  11.                         break;
  12.                        
  13.                 }
  14.                 cur = cur->next;
  15.         }
  16.         return pos;
  17. }
复制代码
2.2.9 中间插

  1. //中间插
  2. void ListInsert(ListNode* pos, ListData x)
  3. {
  4.         assert(pos);
  5.         /*ListNode* newNode = BuyListNode(x);
  6.         ListNode* posPrev = pos->prev;
  7.         newNode->next = pos;
  8.         pos->prev = newNode;
  9.         posPrev->next = newNode;
  10.         newNode->prev = posPrev;*/
  11.         ListPushFront(pos->prev, x);
  12. }
复制代码
2.3 中间删

  1. //中间删
  2. void ListErase(ListNode* pos)
  3. {
  4.         ListNode* posPrev = pos->prev;
  5.         ListNode* posNext = pos->next;
  6.         posPrev->next = posNext;
  7.         posNext->prev = posPrev;
  8.         free(pos);
  9. }
复制代码
2.3.1 表现

  1. //显示
  2. void ListPrint(ListNode* phead)
  3. {
  4.         assert(phead);
  5.         ListNode* tail = phead->next;
  6.        
  7.         while (tail != phead)
  8.         {
  9.                 printf("%d ", tail->data);
  10.                 tail = tail->next;
  11.         }
  12.        
  13.         printf("\n");
  14. }
复制代码
2.3.2 清空链表

  1. void ListClear(ListNode** phead)
  2. {
  3.         ListNode* cur = (*phead)->next;
  4.         while (cur != *phead)
  5.         {
  6.                 ListNode* next = cur->next;
  7.                 free(cur);
  8.                 cur = next;
  9.         }
  10.         (*phead)->next = *phead;
  11.         (*phead)->prev = *phead;
  12. }
复制代码
2.3.3 烧毁链表

  1. //销毁链表
  2. void ListDestory(ListNode** phead)
  3. {
  4.         ListClear(phead);
  5.         free(*phead);
  6. }
复制代码
  双链表优点:插入时间复杂度比单链表更低,可以前驱访问。
  缺点:不能随机访问。
   3 次序表和链表的区别

差异点次序表链表
存储空间上物理上一定一连逻辑上一连,物理上不一定一连
随机访问支持O(1)不支持O(N)
任意位置插入或者删除元素可能需要搬移元素,效率低O(N)只需修改指针指向
插入动态次序表,空间不敷时需要扩容没有容量概念
应用场景元素高效存储+频繁访问任意位置插入和删除频繁
缓存使用率


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

梦应逍遥

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表