数据结构(二):线性表之链式存储函数实现
线性表的链式存储的主要操作的实现:
注: 该链表包含头结点。
0. 头文件的宏定义:
#define SUCCESS 1
#define FAILED 0
typedef int Status;
typedef int dataType;
typedef struct node_{
dataType data;
struct node_ *next;
}LinkNode_st, *LinkNode_pt;
1. 创建链表头:
由于需要创建头结点,然后将头指针指向头结点,如果需要形参,需要传递头指针的地址。
/* 1. 链表的头结点创建 */
LinkNode_pt LinkList_create_head(LinkNode_pt *head)
{
LinkNode_pt node;
node= (LinkNode_pt)malloc(sizeof(LinkNode_st));
if(!node) printf("malloc error\n");
if(head)
*head = node;
return node; /*函数调用结束后,malloc的空间不会释放,因此node的值可以作为返回值*/
}
2. 链表的插入:
/*
* 1 <= location <= length(linkList);
*/
Status LinkList_insert(LinkNode_pt head, int location, dataType data)
{
LinkNode_pt pcur = head;
LinkNode_pt node = NULL;
int i = 1;
if(!head){
printf(" The LinkList ' head node is NULL \n");
return FAILED;
}
if(location<=0) {
printf("The location' value range is 1<= location <= LinkList_getLength(head) \n");
return FAILED;
}
while(pcur && (i<location)){
pcur = pcur->next;
i++;
}
if(!pcur || i>location)
printf("Location is out of range\n");
node = (LinkNode_pt)malloc(sizeof(LinkNode_st));
if(!node){
printf("LinkList_insert : malloc error\n");
return FAILED;
}
memcpy(&node->data, &data, sizeof(dataType));
node->next = pcur->next;
pcur->next = node;
return SUCCESS;
}
3. 链表的删除:
/*
* 删除指定位置的节点: 1<= location <= length(linkList)
*/
Status LinkList_delByLoc(LinkNode_pt head, int location, dataType * data)
{
LinkNode_pt pcur = head;
LinkNode_pt node;
int i = 1;
if(!pcur){
printf("The LinkList ' head node is NULL\n");
return FAILED;
}
if(location<=0){
printf("The location is out of range\n");
return FAILED;
}
while(pcur && (i<location)){
pcur = pcur->next;
i++;
}
if(!pcur || (i>location)){
printf("location is out of range\n");
return FAILED;
}
node = pcur->next;
memcpy(data, &node->data, sizeof(dataType));
pcur->next =node->next;
free(node);
return SUCCESS;
}
/*
* 匹配某个数据的值,如果相等,则进行删除,cnt为删除的结点个数
*/
Status LinkList_delByData(LinkNode_pt head, dataType * data, int cnt)
{
LinkNode_pt pcur = head;
LinkNode_pt node = NULL;
if(!pcur){
printf("The LinkList ' head node is NULL\n");
return FAILED;
}
cnt = 0;
while(pcur && pcur->next){
if(!memcmp(data, &pcur->next->data, sizeof(dataType))){
node = pcur->next;
pcur->next = node->next;//1 跳过node节点
cnt++;
free(node);
continue;
}
pcur = pcur->next;
}
if(!pcur ->next && !cnt){
printf("This linkList doesn't have this node\n");
return FAILED;
}else{
return SUCCESS;
}
}
4. 获取指定位置节点的元素的值
Status LinkList_getElem(LinkNode_pt head, int location, dataType data)
{
LinkNode_pt pcur = head;
LinkNode_pt node= NULL;
int i = 1;
if(!pcur){
printf("This LinkNode ' head is NULL\n");
return FAILED;
}
while(pcur->next && i<location){ /*可以不使用next*/
pcur = pcur->next;
i++;
}
if(!pcur->next){
printf("This location is out of range\n");
return FAILED;
}
if(i == location){
node = pcur->next;
memcpy(&data, &node->data, sizeof(dataType));
return SUCCESS;
}else{
return FAILED;
}
}
5. 整个链表的创建(指定节点个数)
Status LinkList_create(LinkNode_pt *head, int nodeNum)
{
LinkNode_pt node;
int i = 0;
if(!head){
printf("The head is NULL\n");
return FAILED;
}
*head = (LinkNode_pt)malloc(sizeof(LinkNode_st));
if(!*head){
printf("LinkList_create : head node malloc error\n");
return FAILED;
}
(*head)->next = NULL;
#ifdef TAILINSERT //1 尾插法
LinkNode_pt pcur, tail;
pcur = *head;
pcur->data = 0;
pcur->next = NULL;
tail = pcur;
while(i<nodeNum){
node = (LinkNode_pt)malloc(sizeof(LinkNode_st));
if(!node){
printf("LinkList_create: node malloc error\n");
return FAILED;
}
node->data = i+1; /*可以修改*/
node->next = NULL;
tail->next = node;
tail = node;
++i;
}
#else //1 头插法
while(i<nodeNum){
node = (LinkNode_pt)malloc(sizeof(LinkNode_st));
if(!node){
printf("LinkList_create: node malloc error\n");
return FAILED;
}
node->data = i+1; /*可以修改*/
node->next = (*head)->next;
(*head)->next = node;
++i;
}
#endif
return SUCCESS;
}
6. 整个链表的删除:
/*
* 对于包含头结点的链表,空链表只有一个头结点和指向头结点的头指针
* 该函数删除有除最后一个节点外的所有节点,并将尾节点重新作为新的头节点
*/
Status LinkList_delete(LinkNode_pt *head) /*未保留头结点*/
{
if(!head){
printf("The head is NULL\n");
return FAILED;
}
#ifdef DOUBLE_POINTER //1 只需维持一个指针,充分利用二级指针
LinkNode_pt node;
while(*head && (*head)->next){ /*当前节点和下一节点均不为空*/
node = *head;
*head = (*head)->next; /*这个函数有点剑走偏锋,应该用Linus吐槽用二级指针时的那种*/
free(node);
}
memset((*head)->data,0,sizeof((*head)->data));
#else //1 维持两个指针
LinkNode_pt p,q;
int i=0;
p = (*head)->next;
while(p){
q = p->next;
free(p);
p = q;
}
(*head)->next = NULL;
#endif
return SUCCESS;
}