1、前言;2、双向链表的定义;3、双向链表的操作;4、完整的demo;5、完整代码;6、总结
1、前言
在前面的学习中,对"指针”这个概念有了一定的印象,同样也学习了简单链表的使用,双向链表的学习是对这两个个概念加以更深入的理解与学习,下面就由我来给大家梳理一遍我对双向链表的理解吧!
2、双向链表的定义:
在我的理解中,双向链表就如同体育课上的排队一样,老师会要求同学们记住自己的前后位置是 谁,其中站在第一排的同学需要记住自己是第一排的同学以及自己的后面是谁;最后一排的同学要记住自己的前面是谁以及自己是最后一排的同学。这样一排队伍就相当于一个 双向链表。
3、双向链表的操作:
①双向链表的定义
typedef int DataType;
typedef struct node
{
DataType data; /*数据域*/
struct node *next; /*指针域*/
}DoubleList, DoubleNode;
②双向链表可以双向访问链表,它有一个向前的指针p->prior,有个向后的指针p->next;
p->prior=NULL;
p->next=NULL;
/*链表为空时让头指向尾*/
(*head)->next=(*tail);
(*tail)->prior=(*head);
③ 初始双向链表,向内存中申请节点的内存,若能满足返回TRUE,反之返回FALSE
int init(DoubleList **Head)
{
if(1)
{
/*申请内存*/
(*Head) = (DoubleList*)malloc(sizeof(DoubleList));
/*判断内存申请是否成功*/
if(*Head == NULL)
{
printf("申请内存错误, 初始化失败![404]\n");
return 404;
}
(*Head)->next = NULL;
return 0;
}
else
{
printf("该链表已经初始化!请删除后再执行此操作![400]\n");
return 400;
}
}
④插入(insert)元素之头插法
int insert_head(DoubleList **Head, DataType x)
{
DoubleNode *newNode;
if(0)
{
printf("链表未初始化![1000]\n");
return 1000;
}
newNode = (DoubleNode*)malloc(sizeof(DoubleNode));
if(!newNode)
{
printf("申请节点内存空间失败![1001]\n");
return 1001;
}
newNode->data = x;
newNode->next = (*Head)->next;
(*Head)->next = newNode;
return 0;
}
⑤插入元素(insert)之尾插法
int insert_tail(DoubleList **Head, DataType x)
{
DoubleNode *newNode;
DoubleNode *p;
if(0)
{
printf("链表未初始化![1000]\n");
return 1000;
}
newNode = (DoublekNode*)malloc(sizeof(DoubleNode));
if(!newNode)
{
printf("申请节点内存空间失败![1001]\n");
return 1001;
}
newNode->data = x;
newNode->next = NULL;
p = (*Head);
while(p->next)
{
p = p->next;
}
p->next = newNode;
return 0;
}
⑥插入元素(insert)之在指定位置插入元素,同时也要判断该元素是否符合条件,元素须符合0-length+1的位置
int insert(DoubleList **Head, int i, DataType x)
{
int a;
DooubleNode *p;
DoubleNode *newNode;
/*对i进行判断,0<i<=length+1*/
if(i<1 || i>length(*Head)+1)
{
printf("位置i不是链表有效位置![1002]\n");
return 1002;
}
p = (*Head);
a = 1;
while(a<i)
{
a++;
p = p->next;
}
newNode = (DoubleNode*)malloc(sizeof(DoubleNode));
/*此处省略检测newNode是否申请成功*/
newNode->data = x;
newNode->next = p->next;
p->next = newNode;
return 0;
}
⑦删除元素delete
int delete(DoubleList **Head, DataType x)
{
int i;
int a;
DoublekNode *p;
DoubleNode *q; /*要删除的元素x*/
i = find(*Head,x);
if(!i)
{
printf("元素x【%d】不存在!1006\n", x);
return 1006;
}
p = (*Head);
a=1;
while(a<i)
{
a++;
p = p->next;
}
q = p->next;
p->next = q->next;
free(q); /*释放内存*/
return 0;
}
⑧查找元素(find)
int find(DoubleList *Head, DataType x)
{
int i;
DoubleNode *p;
i = 1;
p = Head->next;
while(p && p->data != x) /*while( p!= Head && p->data != x) */
{
i++;
p = p->next;
}
if(!p) /* if(p->next == Head) */
{
return 0;
}
else
{
return i;
}
}
⑨查看链表长度并输出链表
int length(DoubleList *Head)
{
int len=0;
DoubleNode *p;
p = Head->next;
while(p) /* while(p!=Head) */
{
len++;
p = p->next;
}
return len;
}
void print(DoubleList *Head)
{
DoubleNode *p;
int i=0;
p = Head->next;
if(!p) /* if(p!=Head) */
{
printf("链表为空!\n");
return;
}
while(p) /* while(p!=Head) */
{
printf("Node[%d]. = %d\n", ++i, p->data);
p = p->next;
}
}
4、完整的demo
5、完整的代码
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int status;
typedef int elemtype;
typedef struct node{
elemtype data;
struct node * next;
struct node * prior;
}node;
typedef struct node* dlinklist;
status visit(elemtype c){
printf("%d ",c);
}
/*双向链表初始化*/
status initdlinklist(dlinklist * head,dlinklist * tail){
(*head)=(dlinklist)malloc(sizeof(node));
(*tail)=(dlinklist)malloc(sizeof(node));
if(!(*head)||!(*tail))
return ERROR;
/*这一步很关键*/
(*head)->prior=NULL;
(*tail)->next=NULL;
/*链表为空时让头指向尾*/
(*head)->next=(*tail);
(*tail)->prior=(*head);
}
/*判定是否为空*/
status emptylinklist(dlinklist head,dlinklist tail){
if(head->next==tail)
return TRUE;
else
return FALSE;
}
/*尾插法创建链表*/
status createdlinklisttail(dlinklist head,dlinklist tail,elemtype data){
dlinklist pmove=tail,pinsert;
pinsert=(dlinklist)malloc(sizeof(node));
if(!pinsert)
return ERROR;
pinsert->data=data;
pinsert->next=NULL;
pinsert->prior=NULL;
tail->prior->next=pinsert;
pinsert->prior=tail->prior;
pinsert->next=tail;
tail->prior=pinsert;
}
/*头插法创建链表*/
status createdlinklisthead(dlinklist head,dlinklist tail,elemtype data){
dlinklist pmove=head,qmove=tail,pinsert;
pinsert=(dlinklist)malloc(sizeof(node));
if(!pinsert)
return ERROR;
else{
pinsert->data=data;
pinsert->prior=pmove;
pinsert->next=pmove->next;
pmove->next->prior=pinsert;
pmove->next=pinsert;
}
}
/*正序打印链表*/
status traverselist(dlinklist head,dlinklist tail){
/*dlinklist pmove=head->next;
while(pmove!=tail){
printf("%d ",pmove->data);
pmove=pmove->next;
}
printf("\n");
return OK;*/
dlinklist pmove=head->next;
while(pmove!=tail){
visit(pmove->data);
pmove=pmove->next;
}
printf("\n");
}
/*返回第一个值为data的元素的位序*/
status locateelem(dlinklist head,dlinklist tail,elemtype data){
dlinklist pmove=head->next;
int pos=1;
while(pmove&&pmove->data!=data){
pmove=pmove->next;
pos++;
}
return pos;
}
/*返回表长*/
status listlength(dlinklist head,dlinklist tail){
dlinklist pmove=head->next;
int length=0;
while(pmove!=tail){
pmove=pmove->next;
length++;
}
return length;
}
/*逆序打印链表*/
//status inverse(dlinklist head,dlinklist tail){
// dlinklist pmove=tail->prior;
// while(pmove!=head){
// visit(pmove->data);
// pmove=pmove->prior;
// }
// printf("\n");
//}
/*删除链表中第pos个位置的元素,并用data返回*/
status deleteelem(dlinklist head,dlinklist tail,int pos,elemtype *data){
int i=1;
dlinklist pmove=head->next;
while(pmove&&i<pos){
pmove=pmove->next;
i++;
}
if(!pmove||i>pos){
printf("输入数据非法\n");
return ERROR;
}
else{
*data=pmove->data;
pmove->next->prior=pmove->prior;
pmove->prior->next=pmove->next;
free(pmove);
}
}
/*在链表尾插入元素*/
status inserttail(dlinklist head,dlinklist tail,elemtype data){
dlinklist pinsert;
pinsert=(dlinklist)malloc(sizeof(node));
pinsert->data=data;
pinsert->next=NULL;
pinsert->prior=NULL;
tail->prior->next=pinsert;
pinsert->prior=tail->prior;
pinsert->next=tail;
tail->prior=pinsert;
return OK;
}
int main(void){
dlinklist head,tail;
int i=0;
elemtype data=0;
initdlinklist(&head,&tail);
if(emptylinklist(head,tail))
printf("链表为空\n");
else
printf("链表不为空\n");
printf("头插法创建链表\n");
for(i=0;i<100;i++){
createdlinklisthead(head,tail,i);
}
traverselist(head,tail);
for(i=0;i<100;i++){
printf("表中值为%d的元素的位置为",i);
printf("%d位\n",locateelem(head,tail,i));
}
printf("表长为%d\n",listlength(head,tail));
//printf("逆序打印链表");
inverse(head,tail);
for(i=0;i<100;i++){
deleteelem(head,tail,1,&data);
printf("被删除的元素为%d\n",data);
}
traverselist(head,tail);
if(emptylinklist(head,tail))
printf("链表为空\n");
else
printf("链表不为空\n");
printf("尾插法创建链表\n");
for(i=0;i<100;i++)
createdlinklisttail(head,tail,i);
}
// traverselist(head,tail);
// printf("逆序打印链表");
// inverse(head,tail);
}
6、总结
作为一个没学过C语言的我来说,这门数据结构让我学的属实吃力,这门课犹如天书一般的存在,在课堂上想要去尽力听懂也很不容易,在写这篇作业的时候也是东拼西凑,借助各方大佬的鼎立相持才得以完成。
资料借鉴:知乎、博客、度娘、课本。