链表操作,测试下 通过 指向结点的指针以及 指向结点指针的指针 完成 链表操作。
//链表的实现
#include <stdio.h>
#include <malloc.h>
#define ElemType int
#define LIST_INIT_SIZE 20
#define OK 1
#define ERROR 0
typedef struct Node{
int data;
struct Node *next;
}Node, *LinkList;
int CreateList(LinkList *list, int n);
int InsertList(LinkList list, int pos, int n);
int DelList(LinkList *list, int pos, int *n);
int MergeList(LinkList *des_list, LinkList *src_list);//将src_list合并至des_list中,两列表有序 从小到大排列
int ListTraverse(LinkList list); //可传指针,减少复制
int ListLength(LinkList list);
int DestroyList(LinkList *list);//摧毁链表,表头+结点
int ClearList(LinkList *list);//置为空表
int InsertList_p(LinkList *list, int pos, int n);
int LocatePos(LinkList list, int i, LinkList *des);//用des指向list中第i个结点
int MakeNode(LinkList *node, ElemType e);//
int InsFirst(LinkList *list, LinkList p);
int DelFirst(LinkList list, LinkList p);
#define _POINT_
int main()
{
LinkList list_q = NULL;
LinkList list_p = NULL;
LinkList des = NULL;
int n, m;
CreateList(&list_q, 3);
printf("create list,length:%d \n", ListLength(list_q));
ListTraverse(list_q);
MakeNode(&des, 5);
LocatePos(list_q, 2, &des);
InsFirst(&list_q, des);
printf("first insert,length:%d \n", ListLength(list_q));
ListTraverse(list_q);
DelFirst(list_q, des);
printf("first del,length:%d \n", ListLength(list_q));
ListTraverse(list_q);
CreateList(&list_p, 3);
printf("create list,length:%d \n", ListLength(list_q));
ListTraverse(list_p);
MergeList(&list_p, &list_q);
printf("after merge,length:%d \n", ListLength(list_p));
ListTraverse(list_p);
ClearList(&list_p);
printf("after clear,length:%d \n", ListLength(list_p));
ListTraverse(list_p);
//CreateList(&list_q, 3);//list_q在Mergelist中被释放,需重建
#ifndef _POINT_
if (InsertList(list_p, 1, 3))
{
ListTraverse(list_p);
printf(" 1 insert length:%d \n", ListLength(list_p));
}
if (InsertList(list_p, 3, 6))
{
ListTraverse(list_p);
printf(" 2 insert length:%d \n", ListLength(list_p));
}
if (InsertList(list_p, ListLength(list_p) + 1, 5))
{
ListTraverse(list_p);
printf(" 3 insert length:%d \n", ListLength(list_p));
}
if (InsertList(list_p, ListLength(list_p) + 2, 5))
{
ListTraverse(list_p);
printf(" 4 insert length:%d \n", ListLength(list_p));
}
if (InsertList(list_p, ListLength(list_p) + 12, 5))
{
ListTraverse(list_p);
printf(" 4 insert length:%d \n", ListLength(list_p));
}
#else
if (InsertList_p(&list_p, 1, 3))//边界测试
{
printf("1st insert length:%d \n", ListLength(list_p));
ListTraverse(list_p);
}
if (InsertList_p(&list_p, 3, 6))
{
printf("2nd insert length:%d \n", ListLength(list_p));
ListTraverse(list_p);
}
if (InsertList_p(&list_p, ListLength(list_p) + 1, 5))//边界测试
{
printf("3th insert length:%d \n", ListLength(list_p));
ListTraverse(list_p);
}
if (DelList(&list_p, 1, &n))//边界测试
{
printf("del 1st num:%d\n", n);
ListTraverse(list_p);
}
if (DelList(&list_p, ListLength(list_p), &m))//边界测试
{
printf("del last num:%d\n", m);
ListTraverse(list_p);
}
if (InsertList_p(&list_p, ListLength(list_p) + 2, 5)) //边界测试
{
printf("insert len+2 length:%d \n", ListLength(list_p));
ListTraverse(list_p);
}
#endif
return 0;
}
int CreateList(LinkList *list, int n) //创建带表头的链表 从尾到头
{
int i = 0;
LinkList p;
*list = (LinkList)malloc(sizeof(Node));//创建头结点
if(!(*list))
return ERROR;
(*list)->next = NULL;
for (i = 0; i < n; i++)
{
p = (LinkList)malloc(sizeof(Node));
if (!p)
return ERROR;
printf("input data:");
scanf_s("%d",&p->data);
p->next = (*list)->next;
(*list)->next = p;
}
return OK;
}
int ListTraverse(LinkList list)
{
LinkList p = list->next;//指向第一个节点
while(p)
{
printf("%d ",p->data);
p = p->next;
}
printf("\n");
return OK;
}
/*在第pos位置之前添加,1<=n<= length +1*/
int InsertList(LinkList list, int pos, int n)
{
int i = 0;
LinkList p = list; //指向头
LinkList temp;
if(pos < 1)
return ERROR;
for (i = 0; i< pos-1 && p;i++) //使指针 指向 pos - 1 的位置, !p保证 pos-1 <=length+1
{
p = p->next;
}//退出3中可能 (1)i == pos -1 正确 (2)p == null (3)兼有 (2)(3)为超过length+1
if(!p || i != pos-1)
{
printf("beyond the limit\n");
return ERROR; //确认指针 指向 pos - 1 的位置
}
temp = (LinkList)malloc(sizeof(Node));
if (!temp)
{
return ERROR;
}
temp->data = n;
temp->next = p->next;
p->next = temp;
return OK;
}
int DelList(LinkList *list, int pos, int *n)
{
int i;
LinkList p = *list;//p指向标头
LinkList q;
if (pos < 1)
return ERROR;
for(i = 0; (i < pos-1)&&(p->next); i++) //指向pos-1
{
p = p->next;
//边界检测
}
if ((i != pos-1)||(!(p->next)))
return ERROR;
q = p->next;
*n = q->data;
p->next = q->next;
free(q);
return OK;
}
int ListLength(LinkList list)
{
int length = 0;
LinkList p = list;
if (!list)//边界检测
return ERROR;
while (p->next)
{
length++;
p = p->next;
}
return length;
}
int InsertList_p(LinkList *list, int pos, int n)
{
int i = 0;
LinkList *p = list; //指向头
LinkList temp;
LinkList q = *list;
if (pos < 1)
{
return ERROR;
}
for (i = 0; i < pos-1 && q ;i++) //指向 pos - 1 的位置
{
q = q->next;
}
if ( !q || i != pos-1 )
{
printf("beyond limit\n");
return ERROR;
}
temp = (LinkList)malloc(sizeof(Node));
temp->data = n;
temp->next = q->next;
q->next = temp;
return OK;
}
int MergeList(LinkList *des_list, LinkList *src_list)//两列表有序 从小到大排列
{
LinkList des = *des_list;//指向头结点
LinkList p_des = (*des_list)->next;//指向第一个结点
LinkList p_src = (*src_list)->next;
while(p_des && p_src)
{
if (p_des->data <= p_src->data)
{
des->next = p_des;
des = des->next;
p_des = p_des->next;
}
else
{
des->next = p_src;
des = des->next;
p_src = p_src->next;
}
}
des->next = p_des ? p_des : p_src;//
free(*src_list);//释放源链表的头结点
return OK;
}
int DestroyList(LinkList *list)//从表头开始释放
{
LinkList *t_list = list;//*t_list为 标头
LinkList p;
while (*t_list)
{
p = (*t_list)->next;
free(*t_list);
*t_list = p;
}
*list = NULL; //收尾,是list指向空
return OK;
}
int ClearList(LinkList *list)//从第一个结点开始释放
{
LinkList p = (*list)->next;//指向第一个节点
LinkList q;
while(p)
{
q = p->next;
free(p);
p = q;
}
(*list)->next = NULL;
return OK;
}
int LocatePos(LinkList list, int pos, LinkList *des)//用des指向list中第pos个结点
{
LinkList p = list;//p指向头结点
int i = 0;
if (pos < 1)
return ERROR;
while(p && i<pos)//p指向 pos位置,pos次
{
p = p->next;
i++;
}
if(!p || i != pos)
return ERROR;
(*des)->next = p->next;
(*des)->data = p->data;
return OK;
}
int MakeNode(LinkList *node, ElemType e)
{
*node = (LinkList)malloc(sizeof(Node));
if (!*node)
return ERROR;
(*node)->next = NULL;
(*node)->data = e;
return OK;
}
int InsFirst(LinkList *list, LinkList p)//将p指向的结点添加至list第一个位置
{
LinkList t_list = (*list)->next;//指向第一个节点
(*list)->next = p;
p->next = t_list;//p指向结点为第一结点
return OK;
}
int DelFirst(LinkList list, LinkList p)//p删除第一个结点,并用p指向该结点
{
LinkList head = list;
LinkList q = head->next;//p指向第一个节点
if (!q)
return ERROR;
head->next = q->next;
return OK;
}
测试结果:
小结:
对比 int InsertList(LinkList list, int pos, int n); 与 int InsertList_p(LinkList *list, int pos, int n);
上例中对 链表进行插入操作时,既可以 传递 LinkList p_node变量--指向结点的指针,也可传递 LinkList *list指向 链表的指针。理解不同传递参数的意义:
传递 LinkList p_node时,理解为 传递头结点的地址。 (LinkList == Node*)
传递 LinkList *list 时,理解为传递的为链表的地址。 (链表为指向头结点的指针/地址)
传递不同参数的目的:
获取参数拷贝,还是获取地址 修改该参数的内容。