面试中单链表的相关操作也是常考的内容,本博文也是之前学习时的笔记,在此记录下来,以便日后用到,同时欢迎批评指正。
一、基本操作
单链表的基本操作包括链表的创建、销毁、判空、索引、插入、删除等,下面是在链表的相关操作程序,链表的定义如下:
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;
此链表是带有头结点的,因此空链表的形式是 head->next=NULL .
1. 链表的初始化
LinkList InitList(void)
LinkList head = NULL;
head = (LinkList)malloc(sizeof(LNode));
head->data = 0;
head->next = NULL;
return head;
}
2.链表的销毁
void DestoryList(LinkList L)
LinkList pTemp = L->next,
qTemp=L->next;
if (L->next==NULL) //此为空链表不需要再删除
{
printf("the list has already be empty!\n");
}
else{
while(pTemp)
{
qTemp = pTemp->next;
free(pTemp);
pTemp = qTemp;
}
L->next = pTemp;
}
}
3.链表的判空
bool ListEmpty(LinkList L)
if(L->next == NULL)
{
return TRUE;
}
else return FALSE;
}
4.链表的长度
{
LinkList pTemp = L->next;
int NodeCount = 0;
for(;pTemp;pTemp = pTemp->next)
{
NodeCount++;
}
return NodeCount;
}
5.链表的索引
{ //取出第i个节点
LinkList pTemp = L;
int j = 0;
while(pTemp && j<i)
{
pTemp = pTemp->next;
j++;
}
if(!pTemp || j>i)
{
printf("GetElem Error!\n");
exit(0);
}
*e = pTemp->data;
return *e;
}
6.链表的插入
{ //在第i个节点插入e,因此需要找到第i-1节点,然后在其后插入
LinkList Ins,
pTemp = L;
int j = 0;
while(pTemp && j<i-1)
{
pTemp = pTemp->next;
j++;
}
if(!pTemp || j>i-1)
{
printf("Error!\n");
exit(0);
}
Ins = (LinkList)malloc(sizeof(LNode));
if(Ins==NULL) printf("allocate memory error!\n");
Ins->data = e;
Ins->next = pTemp->next;
pTemp->next = Ins;
}
7.链表的删除
{ //删除第i个节点,因此找到第i-1节点,然后删除其后的节点
LinkList Del,
pTemp = L;
int j = 0;
while(pTemp->next && j<i-1)
{
pTemp = pTemp->next;
j++;
}
if(!(pTemp->next) || j>i-1)
{
printf("error!\n");
exit(0);
}
Del = pTemp->next;
pTemp->next = Del->next;
e = Del->data;
free(Del);
}
8. 链表的创建
该操作有两种方法,一种是头插法,另一种是尾插法
void CreateList(LinkList &L,int n)
L = (LinkList)malloc(sizeof(LNode));
if(L == NULL)
{
printf("error!");
exit(0);
}
L->next=NULL;
for( i=0;i<n;i++)
{
p = (LinkList)malloc(sizeof(LNode));
scanf(&p->data);
p->next=L->next;
L->next = p;
}
}
{ //尾插法,每次都是从链表的尾部插入元素,最后把链表的next指针赋值为NULL
L = (LinkList)malloc(sizeof(LNode));
if (L == NULL)
{
printf("error!");
exit(0);
}
L->next = NULL;
pre = L;
for(i=0;i<n;i++)
{
p = (LinkList)malloc(sizeof(LNode));
scanf(&p->data);
pre ->next = p;
pre = p;
}
pre->next = NULL;
}
二、其他操作
1.链表的反转
ListList ReverseList(LinkList L )
LinkList p = L->next;
LinkList prev = NULL,temp = NULL;
while(p!=NULL)
{
temp = p;
p = p->next;
temp->next = prev;
prev = temp;
}
L->next = prev;
return L;
}
链表的反转也可以使用递归来做!
2.删除一个元素x
{ //带有头结点,p为L的第一个元素
LinkList p = L->next;
LinkList prev = NULL,temp = NULL;
while(p!=NULL)
{
temp = p;
p = p->next;
temp->next = prev;
prev = temp;
}
L->next = prev;
return L;
}
3.删除所有重复的元素
void DeleteAllX(LinkList L)
LinkList p = L,
pPrev,
pCurr;
while( p!= NULL)
{
pPrev = p;
pCurr = p->next;
while(pCurr != NULL)
{
if(pCurr->data == p->data)
{
pPrev->next = pCurr->next;
free(pCurr);
pCurr = pPrev->next;
}
else
{
pPrev = pCurr;
pCurr = pCurr->next;
}
}
p = p->next;
}
}
4.判断链表是不是有环
{
LinkList slow = head,
fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast)
break;
}
return !(fast == NULL || fast->next == NULL);
}
如果链表带环的话,找出环的入口,这个原理网上有介绍,算法也一大堆!
5.将链表分为两个链表,一个为奇数序的元素,另一个为偶数序的元素
{
LinkList Lb,pb,pa,pTemp;
Lb = (LinkList)malloc(sizeof(LNode));
pa = La->next;
pb = Lb;
while(pa->next)
{
pTemp = pa->next;
pa->next = pTemp->next;
pb->next = pTemp;
pb = pTemp;
pa = pa->next;
}
pb->next = NULL;
}
6.单链表的插入排序
{
LinkList p,q,pre,r;
p = L->next;
while(p->next)
{
q = p->next;
if(q->data < p->data)
{
pre = L;
r = L->next;
while(r!=p && r->data < q->data)
{
pre = r;
r = r->next;
}
p->next = q->next;
q->next = r;
pre->next = q;
}
else
p = p->next;
}
}
7.单链表的选择排序
void SelectSort(LinkList L)
LinkList p,q,r;
p = L->next;
while(p->next)
{
r = p;
q = p->next;
while(q)
{
if(r->data > q->data)
r = q;
q = q->next;
}
if(r != p)
{
temp = p->data;
p->data = r->data;
r->data = temp;
}
p = p->next;
}
}