线性表链式表示方法
线性表的链式存储特点是用一组任意的存储单元存储线性表的数据元素(这组存取单元很可能在物理上不是连续的)。因此为了表示每个数据元素,出了存储其本身的信息之外,还的存储一个指示其后继的信息。这两部分信息组成数据元素的存储映像,称为结点。包括了一个数据域和一个指针域(为什么可以包括自己类型的指针呢?因为指针在32位CPU上表示4字节大小,大小固定)。
其原理及其实现都是比较简单的,代码如下所示:
#include <stdio.h>
#include <stdlib.h>
typedef struct LNode
{
int data;
struct LNode *next;
}LNode;
bool GetElem_L(LNode *pNode, int i, int *e)
{
if (pNode == NULL || e == NULL)
{
return false;
}
LNode *p = pNode->next;
int pos = 1;
while (p && pos < i)
{
p = p->next;
++pos;
}
if (!p || pos > i)
{
return false;
}
*e = p->data;
return true;
}
bool ListInsert_L(LNode *pNode, int i, int e)
{
LNode *p = pNode;
int pos = 0;
while (p && pos < i - 1)
{
p = p->next;
++pos;
}
if (!p || pos > i - 1)
{
return false;
}
LNode *s = (LNode*)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
bool ListDelete_L(LNode *pNode, int i, int *e)
{
if (pNode == NULL || e == NULL)
{
return false;
}
LNode *p = pNode;
int pos = 0;
while (p->next && pos < i - 1)
{
p = p->next;
++pos;
}
if (!(p->next) || pos > i - 1)
{
return false;
}
LNode *q = p->next;
p->next = q->next;
*e = q->data;
free(q);
return true;
}
void CreateList_L(LNode **pNode, int n)
{
if (pNode == NULL)
{
return;
}
*pNode = (LNode*)malloc(sizeof(LNode));
(*pNode)->next = NULL;
(*pNode)->data = 5;
for (int i = 1; i <= n; i++)
{
LNode *p = (LNode*)malloc(sizeof(LNode));
p->data = i;
p->next = (*pNode)->next;
(*pNode)->next = p;
}
}
void ListDestroy(LNode *pNode)
{
while(pNode)
{
LNode *q = pNode;
pNode = pNode->next;
free(q);
}
}
void tranverse(LNode *pNode)
{
while(pNode)
{
printf("%d\n", pNode->data);
pNode = pNode->next;
}
}
int main()
{
LNode *pList = NULL;
CreateList_L(&pList, 4);
ListInsert_L(pList, 1, 10);
int e = 0;
ListDelete_L(pList, 3, &e);
printf("%d\n", e);
tranverse(pList);
ListDestroy(pList);
return 0;
}
//=======================================================================================
#include <stdio.h>
#include <stdlib.h>
typedef struct tagLinkList
{
int data;
struct tagLinkList *pNext;
} LinkList;
LinkList *createList(unsigned int nodeNum)
{
LinkList *pHeader = NULL;
for(unsigned int i = 0; i < nodeNum; i++)
{
LinkList *pCur = (LinkList*)malloc(sizeof(LinkList));
pCur->data = i;
pCur->pNext = pHeader;
pHeader = pCur;
}
return pHeader;
}
void tranverseList(LinkList *pList)
{
while (pList != NULL)
{
printf("%d\n", pList->data);
pList = pList->pNext;
}
printf("**********************\n");
}
LinkList *BubbleSortList(LinkList *pList) //单链表排序
{
LinkList *q = NULL;
LinkList *tail = NULL;
LinkList *p=(LinkList*)malloc(sizeof(LinkList)); // 使指针p指向新开辟的结点
p->pNext = pList; // 使新结点的next成员指向旧链表的头head
pList = p; // 旧链表头head指向新结点
// 以上三条语句的作用是在旧链表head的前面增加一个结点
// 不严格来说,该语句等同于“head->pNext != tail”
//作用是,如果head所指结点的next成员为NULL,刚结束循环
while (tail != pList->pNext)
{
p = pList;
q = p->pNext; // q总是指向"p所指结点"的下一结点
while (q->pNext != tail) // 当q->next的值为NULL是,表示已达链表结尾
{
if(p->pNext->data > q->pNext->data) // 当前一结点的i值小于后一结点的i值执行下面的语句块
{
p->pNext = q->pNext;
q->pNext = q->pNext->pNext;
p->pNext->pNext = q;
} // 该语句块改变链表的连接顺序,参见下图
p = p->pNext;
q = p->pNext; // 以上两条语句使p、q分别指向各自的下一结点,过程可以参考对数组的冒泡算法
}
tail = q; // 使tail指向"每次排序后的q所指的结点",作用是为下一循环设置条件表示式,从而使每次内循环的次数减少
}
p = pList->pNext; // p指向head->next,也就是p指向旧链表的表头
free(pList); // 释放在函数内新开辟的结点
return(p);
}
int main(void)
{
LinkList *pList = createList(0);
tranverseList(pList);
pList = BubbleSortList(pList);
tranverseList(pList);
}