最近学数据结构的链表,就把单向链表的基本操作列了出来,包括链表的建立,链表的插入和删除,链表的查询和遍历,链表的销毁,链表的排序与逆序,链表的合成。
1.链表的建立
一般有两种方式建立链表,头插法和尾插法。
使用头插法建立的链表步骤少,但输出顺序和输入的相反,而尾插法建立链表多了一个不存在数据域的头节点和尾节点,
但是输出是正序的,而且头节点便于我们的其余操作,所以我们一般用尾插法建链表。
2.操作源码
这里为了测试方便,在主程序中只测试了合成两个有序链表的操作,其它测试都已注释掉。
# include <stdio.h>
# include <stdlib.h>
typedef float ElemType;//用于链表数据类型的确定
typedef int Status;//用于返回类型的确定
# define OK 1
# define ERROR 0
typedef struct Node
{
ElemType data;
struct Node *pNext;
}Node, *pNode;
pNode h_create_list(void);//头插法建立链表
pNode t_create_list(void);//尾插法建立链表
void traverse_list1(pNode);//遍历输出头插法链表
void traverse_list2(pNode);//遍历输出尾插法链表
void malloc_fail(pNode);//内存失败处理函数
Status insert_list(pNode, int, ElemType);//增加一个节点
Status delete_list(pNode, int, ElemType*);//删除一个节点
Status getElem_list(pNode, int, ElemType*);//查找并返回相应位置的元素
Status getIndex_list(pNode, ElemType, int*);//查找并返回相应元素的第一个索引
Status destroy_list(pNode);//链表的销毁
Status sort_list1(pNode);//交换数值的冒泡排序,用于数值类型简单的链表
Status sort_list2(pNode);//交换指针的冒泡排序,用于数值类型复杂的链表
pNode reverse_list(pNode);//逆序链表的非递归算法
pNode merge_list(pNode, pNode);//合并两个有序链表,使之依然有序
int main(void)
{
pNode linkList1 = NULL; //创建一个空链表
pNode linkList2 = NULL;
linkList2 = t_create_list();
linkList1 = t_create_list();
//traverse_list1(linkList1);
//traverse_list2(linkList2);
//insert_list(linkList1, 3, 0);
//insert_list(linkList2, 4, 0);
//float val;
//if (delete_list(linkList2, 1, &val))
// printf("Element deleted:%f\n", val);
//if (getElem_list(linkList2, 4, &val))
//{
// printf("The ele is%f\n", val);
//}
//int i;
//if(getIndex_list(linkList2, 2, &i))
//{
// printf("The index is %d\n", i);
//}
//destroy_list(linkList2);
//traverse_list2(linkList2);
//traverse_list1(linkList1);
//traverse_list2(linkList2);
//traverse_list2(linkList2);
//sort_list2(linkList2);
//traverse_list2(linkList2);
//pNode linkList3 = NULL;
//linkList3 = reverse_list(linkList2);
//traverse_list2(linkList3);
pNode linkList3 = merge_list(linkList1, linkList2);
traverse_list2(linkList3);
return 0;
}
pNode h_create_list(void)
{
int num;//节点数
printf("Nodes: ");
scanf("%d", &num);
pNode pHead = NULL; //空链表,指针初始化必须赋值
for (int i=1; i<=num; i++)
{
printf("node %d: ", i);
pNode pNew = (pNode)malloc( sizeof(Node) );
malloc_fail(pNew);
scanf("%f", &pNew->data);
pNew->pNext = pHead;//将新节点挂到头节点
pHead = pNew;//头节点指向新节点
}
return pHead;
}
pNode t_create_list(void)
{
pNode pHead = (pNode)malloc( sizeof(Node) );//分配一个不存在数据域的头节点,便于链表的操作
//内存分配失败,报错并退出程序
malloc_fail(pHead);
pNode pTail = pHead;//创建一个尾节点,方便循环插入链表操作
pTail->pNext = NULL;
int num;//节点数
printf("Nodes: ");
scanf("%d", &num);
for (int i=1; i<=num; i++)
{
printf("node %d: ", i);
pNode pNew = (pNode)malloc( sizeof(Node) );
malloc_fail(pNew);
scanf("%f", &pNew->data);
pTail->pNext = pNew; //把新节点挂到尾节点后面
pNew->pNext = NULL; //新节点的指针域要放空,这是因为尾节点的指针域要空。
pTail = pNew; //尾节点移动
}
return pHead;
}
void traverse_list1(pNode pHead)
{
pNode p = pHead;
while (p)
{
printf("%f ", p->data);
p = p->pNext;
}
printf("\n");
}
void traverse_list2(pNode pHead)
{
pNode p = pHead->pNext;
while (p)
{
printf("%f ", p->data);
p = p->pNext;
}
printf("\n");
}
void malloc_fail(pNode p)
{
if (p == NULL)
{
printf("Memroy allocate fail!\n");
exit(-1);
}
}
Status insert_list(pNode pHead, int pos, ElemType val)
{
int i=1; //计数器
pNode p = pHead;
//以下为经典算法,能判断pos小于1,或大于节点数+1的情况
while (NULL!=p && i<pos)
{
p = p->pNext;
++i;
}
if (NULL==p || i>pos)
return ERROR;
pNode pNew = (pNode)malloc( sizeof(Node) );
pNew->data = val;
pNew->pNext = p->pNext;
p->pNext = pNew;
return OK;
}
Status delete_list(pNode pHead, int pos, ElemType *val)
{
int i=1;
pNode p = pHead;
while (NULL!=p->pNext && i<pos)
{
p = p->pNext;
i++;
}
if (NULL==p->pNext || i>pos)
return ERROR;
pNode q = p->pNext;
*val = q->data;
p->pNext = q->pNext;
free(q);
q = NULL;
return OK;
}
Status getElem_list(pNode pHead, int pos, ElemType*val)
{
int i=1;
pNode p = pHead;
while (NULL!=p->pNext && i<pos)
{
p = p->pNext;
i++;
}
if (NULL==p->pNext || i>pos)
return ERROR;
*val = p->pNext->data;
return OK;
}
Status getIndex_list(pNode pHead, ElemType val, int*index)
{
int i = 1;
pNode p = pHead->pNext;
while (p != NULL)
{
if (val == p->data)
{
*index = i;
return OK;
}
i++;
p = p->pNext;
}
return ERROR;
}
Status destroy_list(pNode pHead)
{
if (pHead == NULL)
return ERROR;
pNode p = pHead->pNext;
pNode q;
while (p)
{
q = p->pNext;
free(p);
p = q;
}
pHead->pNext = NULL;
return OK;
}
Status sort_list1(pNode pHead)
{
pNode p,pTail;//这个尾指针很重要
ElemType temp;
pTail = NULL;
if (pHead->pNext == NULL)
return ERROR;
while (pHead->pNext != pTail)
{
p = pHead->pNext;
while (p->pNext != pTail)
{
if (p->data > p->pNext->data)
{
printf("%f\n", p->data);
temp = p->pNext->data;
p->pNext->data = p->data;
p->data = temp;
}
p = p->pNext;
}
pTail = p;
}
return OK;
}
Status sort_list2(pNode pHead)
{
pNode pTemp, p, pPre, pTail;//注意前驱指针和尾指针
pTail = NULL;
if (pHead->pNext == NULL)
return ERROR;
while (pHead->pNext != pTail)
{
pPre = pHead;
p = pHead->pNext;
while (p->pNext != pTail)
{
if (p->data > p->pNext->data)
{
pTemp = p->pNext;
pPre->pNext = p->pNext;
p->pNext = p->pNext->pNext;
pPre->pNext->pNext = p;
p = pTemp;
}
p = p->pNext;
pPre = pPre->pNext;
}
pTail = p;
}
return OK;
}
//链表的逆序
pNode reverse_list(pNode pHead)
{
pNode current, p;
if (pHead == NULL)
{
return NULL;
}
current = pHead->pNext;
//轮流交换最后一个结点和第一个结点的位置
while (current->pNext != NULL)
{
p = current->pNext;
current->pNext = p->pNext;
p->pNext = pHead->pNext;
pHead->pNext = p;
}
return pHead;
}
pNode merge_list(pNode La, pNode Lb)
{
pNode Lc, HeadC;
HeadC = La;
Lc = HeadC;
La = La->pNext;
Lb = Lb->pNext;
while (La && Lb)
{
if (La->data > Lb->data)//将data较小的连接到Lc
{
Lc->pNext = Lb;
Lb = Lb->pNext;
}
else
{
Lc->pNext = La;
La = La->pNext;
}
Lc = Lc->pNext;
}
Lc->pNext = La ? La : Lb;//将La 或 Lb剩下的部分连接到Lc
return HeadC;
}
其中有错误或不足之处,望大家多多指正。