顺序表的实现【C语言】
链表和顺序表的区别:
链表在逻辑存储上是连续的,在物理存储上是不连续的。
单链表属于链表的一种,共有2个域,一个是数据域,一个是指向其后继结点的指针域。
-
例如:32位系统存储10个整型数据(int 4个字节):
顺序表存储: 总共需要的堆区空间:40个字节
单链表存储: 总共需要的堆区空间:80个字节
单链表的实现:
-
头指针型
-
头指针—在代码中会使用二级指针
-
带头结点的单链表
-
结构声明
typedef int elemType;
typedef struct Node
{
//数据类型
union //联合体 共同体
{
elemType data; //存储有效数据
int length; //头结点使用,来存储结点个数
};
//结点指针类型
struct Node *next;
}linkedList;
- 方法声明
//初始化
void InitLinkedList(linkedList *head);
//销毁
void DestoryLinkedList(linkedList *head);
//求长度
int getLength(linkedList *head);
//判空
bool IsEmpyt(linkedList *head);
//插入
bool InsertLinkedList(linkedList *head,elemType value,int pos);//插入
bool InsertLinkedlistHead(linkedList *head,elemType value);//头插
bool InsertLinkedListRear(linkedList *head,elemType value);//尾插
// 删除
bool DeleteLinkedList(linkedList *head, int pos);
bool DeleteLinkedListHead(linkedList *head);
bool DeleteLinkedListRear(linkedList *head);
bool DeleteLinkedListValue(linkedList *head, elemType value);//按值删除
// 显示
void ShowLinkedList(linkedList *head);
- 方法实现
#include<malloc.h>
#include"linkedList.h"
//申请新结点的函数
static linkedList *ApplyNode(elemType value,linkedList *point)
{
linkedList *new_node=(linkedList*)malloc(sizeof(linkedList));
if(new_node==0) return NULL;
new_node->data =value;
new_node->next=point;
return new_node;
}
//初始化
void InitLinkedList(linkedList* head)
{
if(head==NULL) exit(0);
head->length =0;
head->next =NULL;
}
//判空
bool IsEmpty(linkedList *head)
{
if(head==NULL) exit(0);
return !getLength(head);
}
//销毁
void DestoryLinkedList(linkedList *head)
{
if(head==NULL) exit(0);
while(!IsEmpyt(head))
{
DeleteLinkedListHead(head);
}
}
//长度
inline int getLength(linkedList *head)
{
if(head==NULL) exit(0);
return head->length ;
}
//插入
bool InsertLinkedList(linkedList* head,elemType value,int pos)
{
if(head==NULL) exit(0);
if(pos<0 || (pos> getLength(head))) return false;
linkedList *p;
p=head;
while(pos)
{
p=p->next ;
pos--;
}
linkedList *s=ApplyNode(value,p->next );
if(s==NULL) return false;
s->next =p->next ;
p->next =s;
head->length ++;
return true;
}
bool InsertLinkedListHead(linkedList *head,elemType value)
{
if(head==NULL) exit(0);
return InsertLinkedList(head,value,0);
}
bool InsertLinkedListRear(linkedList *head,elemType value)
{
if(head==NULL) exit(0);
return InsertLinkedList(head,value,getLength(head));
}
//删除
bool DeleteLinkedList(linkedList *head,int pos)
{
if(head==0) exit(0);
if(pos<0 || pos>=getLength(head)) return false;
linkedList *p=head;
while(pos)
{
p=p->next ;
pos--;
}
linkedList *t;
t=p->next;
p->next=t->next ;
free(t);
head->length --;
return true;
}
bool DeleteLinkedListHead(linkedList *head)
{
if(head==0) exit(0);
return DeleteLinkedList(head,0);
}
bool DeleteLinkedListRear(linkedList *head)
{
if(head==0) exit(0);
return DeleteLinkedList(head,getLength(head)-1);
}
//考虑有重复值的情况
bool DeleteLinkedListValue(linkedList *head,elemType value)
{
if(head==NULL) exit(0);
linkedList *p=head;
linkedList *q=head->next ;
while(q!=NULL)
{
if(q->data == value)
{
p->next =q->next ;
free(q);
q=p->next ;
head->length --;
}
else
{
p=q;
q=q->next ;
}
}
return true;
}
void ShowLinkedList(linkedList *head)
{
if(head==NULL) exit(0);
linkedList *p=head;
while(p->next !=NULL)
{
printf("%d ",p->data);
p=p->next ;
}
printf("\n");
}
- 代码测试
int main()
{
linkedList head;
InitLinkedList(&head);
for(int i=1;i<6;i++)
{
InsertLinkedListHead(&head,i);
}
ShowLinkedList (&head);
printf("单链表长度:%d\n",getLength(&head));
int pos;
printf("请输入要删除的位置:");
scanf("%d",&pos);
DeleteLinkedList (&head,pos);
printf("单链表长度:%d\n",getLength(&head));
printf("再删除首结点和尾结点;\n");
DeleteLinkedListHead (&head);
DeleteLinkedListRear (&head);
ShowLinkedList (&head);
printf("单链表长度:%d\n",getLength(&head));
DestoryLinkedList (&head);
return 0;
}
运行结果:
练习:
1、找倒数第k个结点
2、将单链表逆置 -- 结点逆置
3、O(1)删除非尾结点p
4、判断两个单链表是否相交并返回相交的第一个结点
5、判断单链表是否有环,如果有,返回入环的第一个结点
代码:
1、找倒数第k个结点
//找倒数第k个结点
bool FindK(linkedList *head,int k)
{
if(head==NULL) exit(0);
if(k<0 || (k> getLength(head))) return false;
linkedList *p;
p=head->next;
int t=getLength(head)-k;
while(t)
{
p=p->next ;
t--;
}
printf("倒数第%d个结点为:%d\n",k,p->data );
}
int main()
{
linkedList head;
InitLinkedList(&head);
for(int i=1;i<6;i++)
{
InsertLinkedListHead(&head,i);
}
ShowLinkedList (&head);
printf("单链表长度:%d\n",getLength(&head));
reverse(&head);
ShowLinkedList (&head);
int k;
printf("请输入要查找的倒数序号:");
scanf("%d",&k);
FindK(&head,k);
return 0;
}
运行结果:
2、将单链表逆置 – 结点逆置
void reverse(linkedList *head)
{
if(head==NULL) exit(0);
linkedList *p,*q;
p=head->next;//指向首结点
head->next =NULL;//链表置空
while(p)
{
q=p;
p=p->next ;
q->next =head->next ;
head->next =q;//修改头节点指针
}
}
int main()
{
linkedList head;
InitLinkedList(&head);
for(int i=1;i<6;i++)
{
InsertLinkedListHead(&head,i);
}
ShowLinkedList (&head);
printf("单链表长度:%d\n",getLength(&head));
reverse(&head);
ShowLinkedList (&head);
return 0;
}
运行结果:
3、O(1)删除非尾结点p
//删除非尾结点
bool DelNode(linkedList *head,linkedList *p)
{
if(head==NULL) exit(0);
if(p->next ==NULL) return false;
linkedList *q=head;
while(q->next !=p)
{
q=q->next ;
}
q->next=p->next ;
free(p);
head->length --;
return true;
}
int main()
{
linkedList head;
InitLinkedList(&head);
for(int i=1;i<6;i++)
{
InsertLinkedListHead(&head,i);
}
ShowLinkedList (&head);
printf("单链表长度:%d\n",getLength(&head));
DelNode(&head,head.next->next );
ShowLinkedList (&head);
printf("单链表长度:%d\n",getLength(&head));
return 0;
}
运行结果:
4、判断两个单链表是否相交并返回相交的第一个结点
5、判断单链表是否有环,如果有,返回入环的第一个结点