单链表:每个节点只有一个指向后一个节点的指针。
循环链表:最后一个节点的指针指向该循环链表的第一个节点或者表头节点。
双向链表:节点除了含有数据域外,还有两个指针,一个指向后继节点,一个指向前驱节点。
双向循环链表:将双向链表首尾相连。
【 链表插入顺序补充说明】:
单链表插入顺序:
/* 节点p的后面插入指针s */
s->next = p->next; //先解决插入节点的后继
p->next = s; //再解决前节点的后继
双向循环链表插入顺序:
/* p节点后面插入新节点s */
s->left = p; //先解决新插入节点的前驱和后继
s->right = p->right;
p->right->left = s; //再解决后节点的前驱
p->right = s //最后解决前节点的后继
typedef struct node{
int data; //数据域
node *next; //指向下一个节点
}node;
/* 创建带头单链表 */
node *list_create()
{
int i = 0;
node *head, *cur, *tail;
int x = 0;
head = (node *)malloc(sizeof(node)); // 创建头节点
while(1){
scanf("%d", &x); // 输入节点数据
cur = (node *)malloc(sizeof(node));
cur->data = x;
if(++i == 1){ //链表只有一个元素
head->next = cur; //连接到head后面
}esle{
tail->next = cur; //连接到链表尾端
}
tail = cur; //tail指向末节点
}
tail->next = NULL; //链表的最后一个指针为空
return head;
}
/* 获取链表长度 */
int list_length(node *head)
{
int len = 0;
node *cur;
cur = head->next;
while(cur != NULL){
len++;
cur = cur->next;
}
return len;
}
/* 单链表打印 */
void list_show(node *head)
{
node *cur;
int index = 0;
if(head->next == NULL){
printf("List is empty!");
return;
}
cur = head->next;
while(cur != NULL){
printf("The %dth node data is: %d\n", ++index, cur->data);
cur = cur->next;
}
}
/*
* 通过位置查找节点,返回节点指针
* 位置0返回head节点
*/
node *list_search_node(node *head, int pos)
{
node *p = head->next;
if(pos < 0){
return NULL;
}
if(pos == 0){
return head;
}
if(p == NULL){ //链表为空
return NULL
}
while(--pos){
if((p = p->next) == NULL){
break;
}
}
return p;
}
node *list_insert_node(node *head, int pos, int data)
{
node *item = NULL;
node *p;
item = (node *)malloc(sizeof(node));
item->data = data;
if(pos == 0){
head->next = item;
return head;
}
p = list_search_node(head, pos);
if(p != NULL){
item->next = p->next;
p->next = item;
}
return head;
}
node *list_delete_node(node *head, int pos)
{
node *item = NULL;
node *p = head->next;
if(p == NULL){
return NULL;
}
p = list_search_node(head, pos - 1);
if(p != NULL && p->next != NULL){
item = p->next ;
p->next = item->next;
p->next = item->next;
free(item);
item = NULL;
}
return head;
}
node *list_reverse(node *head)
{
node *p, *q, *r;
if(head->next == NULL){
return head;
}
p = head->next;
q = p->next; //保存第二个节点
p->next = NULL; //原第一个节点翻转
while(q != NULL){
r = q->next; //保存当前下一个节点
q-next = p; //指针方向翻转
p = q; //p指针右移
q = r; //q指针右移
}
head->next = p; //头节点指向原来末尾的节点
return head;
}
node *list_search_middle(node *head)
{
int i = 0;
int j = 0;
node *cur = NULL;
node *mid = NULL;
cur = mid = head->next;
while(cur != NULL){
if(i/2 > j){
j++;
mid = mid->next;
}
i++;
cur = cur->next;
}
return mid;
}
node *list_insertSort(void)
{
int data = 0;
node *head = NULL, *new, *cur, *pre;
while(1){
scanf("%d", &data);
new = (node *)malloc(sizeof(node));
new->data = data;
new->next = NULL;
if(head == NULL){
head = new;
continue;
}
if(new->data <= head->data){
new->next = head; //head之前插入节点
head = new;
continue;
}
cur = head;
while(new->data > cur->data && cur->next != NULL){ //找到插入位置
pre = cur;
cur = cur->next;
}
if(cur->data >= new->data){
pre->next = new; //new插入到pre和cur之间
new->next = cur;
}
else
cur->next = new; //new插入cur之后
}
return head;
}
方法:两个指针,一个指针偏移个节点,另一个偏移2个节点。
bool list_isLoop(node *head, node **start)
{
node *p1 = head, *p2 = head;
if(head == NULL || head->next == NULL){
return false;
}
do{
p1 = p1->next;
p2 = p2->next-next;
}while(p2 && p2->next && p1 = p2);
if(p1 == p2){
*start = p1;
return ture;
}
else
return false;
}
node *list_insert_node(node *head, node *item)
{
node *p = head;
node *q = NULL;
while(p->data < item->data && p != NULL){
q = p;
p = p->next;
}
if(p == head){
item->next = p;
return item;
}
q->next = item;
item->next = p;
return head;
}
/* 两个有序链表合并 */
node *list_merge(node *head1, node *head2)
{
node *head;
node *p ;
node *p_next;
if(head1 == NULL){
return head2;
}else if(head2 == NULL){
return head1;
}
if(list_length(head1) >= list_length(head2)){
head = head1;
p = head2;
}else{
head = head2;
p = head1;
}
while(p != NULL){
p_next = p->next;
head = list_insert_node(head, p);
p = p_next
}
return head;
}
定义双向链表节点:
typedef struct DNODE{
int data;
dnode *left; //前驱
dnode *right; //后继
}dnode;
/* 创建新节点 */
dnode * dlist_create_node(int data)
{
dnode *p = (dnode *)malloc(sizeof(dnode));
p->data = data;
p->left = p->right = p; //创建新节点时让前驱和后继都指向自身
return p;
}
/* 创建头节点 */
dnode *dlist_create_node(int head)
{
dnode *p = (dnode *)malloc(sizeof(dnode));
p->data = head;
p->left = p->right = p; //创建新节点时让前驱和后继都指向自身
return p;
}
/* 创建双链表 */
dnode *dlist_create(dnode *head, int data)
{
dnode *new = dlist_create_node(data);
dnode *p = head ,*q;
while(p != NULL){
q = p;
p = p->right;
}
q->right = new;
new->left = q;
return head;
}
void dlist_show(dnode *head)
{
dnode *p = NULL;
if(head == NULL){
return ;
}
p = head;
while(p != NULL){
printf("%d ", p->data);
p = p->right;
}
printf("\n");
}
dnode *dlist_search_node(dnode *head, int data)
{
dnode *p = head;
if(head == NULL)
return NULL;
while(p->right != NULL && p->data != data){
p = p->right;
}
if(p->right == NULL)
return NULL;
return p;
}
void dlist_insert_node(dnode *node, int data)
{
dnode *new = dlist_create_node(data);
dnode *p = NULL;
if(node == NULL)
return NULL;
if(node->right == NULL){
node->right = new;
new->left = node;
}else{
new->right = node->right; //先连new的后继
node->right->left = new; //后节点的前驱指向new
node->right = new; //前节点指向new
new->left = node; //new的前驱
}
}
dnode *dlist_deletenode(dnode *head, int data)
{
dnode *tmp = NULL;
dnode *p = dlist_search_node(head, data);
if(p == NULL){
return NULL;
}else if(p->left == NULL){ //第一个节点
head = p->right;
if(head != NULL)
head->left = NULL;
}else if(p->right == NULL){ //最后节点
p->left->right = NULL;
}else{
p->left->right = p->right;
p->right->left = p->left;
}
free(p);
p = NULL;
return head;
}