双向链表的增删改查,此双向链表没有使用空的头链表,直接第一个链表就可以存值。
//cat chapter2_doublelink.h
#ifndef _DOUBLE_LINK_
#define _DOUBLE_LINK_
typedef struct GList {
int data;
struct GList *prev;
struct GList *next;
} GList;
GList * g_list_new(void);
int g_list_free(GList * p1);
GList * g_list_preinsert(GList * p1, GList* p2);
GList * g_list_appand(GList *p1, GList * p2);
int g_list_print_all(const GList *p1);
GList * g_list_get_post_link(const GList *p1, int pos);
int g_list_post_insert(GList **head, int pos, GList *p2);
GList * g_list_del_link(GList * p1, GList *p2);
void * g_list_destroy(GList * p1);
#endif
root@ubuntu:data-struct# cat double_link.c
#include "chapter2_doublelink.h"
#include
#include
#include
GList * g_list_new(void)
{
GList * p1 = NULL;
p1 = malloc(sizeof(GList));
if (p1) {
p1->prev = p1;
p1->next = p1;
p1->data = 0;
}
return p1;
}
int g_list_free(GList * p1)
{
if (p1) {
free(p1);
return 0;
}
else {
return -1;
}
}
GList * g_list_preinsert(GList * p1, GList* p2)
{
if ( p1 ) {
p2->next = p1;
p2->prev = p1->prev;
p1->prev->next = p2;
p1->prev = p2;
}
return p2;
}
GList * g_list_appand(GList *p1, GList * p2)
{
if (p1) {
p2->next = p1;
p2->prev = p1->prev;
p1->prev->next = p2;
p1->prev = p2;
return p1;
}
else {
return p2;
}
}
GList * g_list_del_link(GList * p1, GList *p2)
{
int i = 0;
GList *p3 = p1;
while (p3) {
if (i != 0 && p3 == p1) {
break;
}
i++;
if (p3->data == p2->data) {
if (p3->next == p3) {
g_list_free(p3);
return NULL;
}
else {
p3->prev->next = p3->next;
p3->next->prev = p3->prev;
if (i == 1) {
p1 = p3->next;
}
g_list_free(p3);
return p1;
}
}
else {
p3 = p3->next;
}
}
return p1;
}
void * g_list_destroy(GList * p1)
{
if (p1) {
GList *p2 = p1;
GList *p3 = p2->next;
while (p2) {
g_list_free(p2);
if (p3 == p1) {
break;
}
p2 = p3;
p3 = p3->next;
}
}
return NULL;
}
int g_list_print_all(const GList *p1)
{
const GList *p2 = p1;
int i = 0;
printf("\n****** start of list ******\n");
while (p2) {
if ( i != 0 && p2 == p1) {
break;
}
i++;
printf("link[%d]:%d\t", i, p2->data);
p2 = p2->next;
}
printf("\n===== end of list =====\n");
return i;
}
int g_link_get_len(const GList *p1)
{
const GList *p2 = p1;
int i = 0;
while (p2) {
if ( i != 0 && p2 == p1) {
break;
}
i++;
p2 = p2->next;
}
return i;
}
GList * g_list_get_post_link(const GList *p1, int pos)
{
int i = 0;
const GList* p2 = p1;
for (; p2; p2 = p2->next ) {
if (i != 0 && p2 == p1) {
break;
}
++i;
if (i == pos) {
return (GList*)p2;
}
}
return NULL;
}
int g_list_post_insert(GList **head, int pos, GList *p2)
{
int ret = -1;
GList *p1 = *head;
GList *p3 = NULL;
if (pos == 1) {
p3 = g_list_preinsert(p1, p2);
*head = p3;
ret = 0;
}
else {
p3 = g_list_get_post_link(p1, pos-1);
if (p3) {
p2->prev = p3;
p2->next = p3->next;
p3->next->prev = p2;
p3->next = p2;
ret = 0;
}
}
return ret;
}
int test()
{
int data;
GList * head = NULL, *p1;
printf("Input your link int data(no-number will finish):\n");
while (1 == scanf("%d", &data)) {
p1 = g_list_new();
if (p1) {
head = g_list_appand(head, p1);
p1->data = data;
}
else {
exit(-1);
}
printf("Input your link int data(no-number will finish):\n");
while ( getchar() != '\n') ;
}
g_list_print_all(head);
while ( getchar() != '\n') ;
printf("insert to prehead, input the insert data:\n");
if (scanf("%d", &data) == 1) {
p1 = g_list_new();
p1->data = data;
head = g_list_preinsert(head, p1);
g_list_print_all(head);
}
printf("insert to 3 pos, input the insert data:\n");
while ( getchar() != '\n') ;
if (scanf("%d", &data) == 1) {
p1 = g_list_new();
p1->data = data;
if (g_list_post_insert(&head, 3, p1) >= 0) {
printf("insert to pos 3 error!!\n");
}
g_list_print_all(head);
}
return 0;
}
==================================链表的使用=====================
/*
使用链表实现无限大整数的加减。
一个链表来装无限大整数a1,另一个链表来装a2,目前先支持两个数都是正整数。
加法可以工作,减法得到负数的时候有bug,为了不卡进度,先不调了,有需要再搞。
*/
int g_list_print_number(const GList *p1)
{
const GList *p2 = p1;
int i = 0;
printf("\n****** start of list ******\n");
while (p2) {
if ( i != 0 && p2 == p1) {
break;
}
i++;
if (p2->data<0) {
printf("-");
}
//printf("link[%d]:%d ",i, p2->data);
printf("%d ",p2->data);
p2 = p2->next;
}
printf("\n===== end of list =====\n");
return i;
}
//len(p1) >= len(p2), small_len = MIN(len p1, len p2)
GList * g_link_opr(GList * p1, GList * p2, char oper, int small_len)
{
GList * res = NULL, *p11 = p1, *p22 = p2, *tmp = NULL;
int borrow = 0, data1 = 0, data2 = 0, i = 0;
if (!p1 || !p2) return NULL;
p11 = p11->prev;
res = p11;//the end.
p22 = p22->prev;
while (i < small_len) {
data1 = p11->data;
data2 = p22->data;
switch (oper) {
case '+':
if (borrow) {
data1++;
borrow = 0;
}
p11->data = (data1 + data2)%100000000;
if ((data1 + data2)/100000000) {
borrow = 1;
}
break;
case '-':
if (borrow) {
data1--;
borrow = 0;
}
p11->data = (data1 - data2);
if (p11->data < 0) {
p11->data = -1 * tmp->data;
borrow = 1;
}
break;
default:
printf("oper:%c does not support yet!\n", oper);
}
p11 = p11->prev;
p22 = p22->prev;
i++;
}
while (borrow) {
if (p11 != res) {
data1 = p11->data;
if (oper == '+') {
data1++ ;
p11->data = data1 % 100000000;
borrow = 0;
if ( data1/100000000 ) {
borrow = 1;
}
}
else {// '-'
data1--;
if (data1 < 0) {
borrow = 1;
data1 = -1 * data1;
}
else {
borrow = 0;
}
p11->data = data1 % 100000000;
}
p11 = p11->prev;
}
else {
tmp = g_list_new();
p1 = g_list_preinsert(p1, tmp);
if (oper == '+') {
tmp->data = 1;
}
else { //'-'
tmp->data = -1;
}
}
}
return p1;
}
int main()
{
int data = 0, str_len = 0;
char opr = '+';
char tmp_str[1024] = {0}, *ptr = NULL, *get = NULL;
GList * head1 = NULL,* head2 = NULL, *p1;
printf("Input first number:");
fgets(tmp_str, sizeof(tmp_str), stdin);
str_len = strlen(tmp_str);
ptr = tmp_str + str_len - 1;
while (ptr >= tmp_str) {
*ptr = 'q';
ptr -= 8;
if (ptr < tmp_str) get = tmp_str;
else get = ptr;
sscanf(get, "%8d", &data);
if(data < 0) {
printf("number < 0 does not support yet\n");
exit(-1);
}
p1 = g_list_new();
if (p1) {
head1 = g_list_preinsert(head1, p1);
p1->data = data;
}
else {
exit(-1);
}
}
g_list_print_number(head1);
//printf("tem:%s", tmp_str);
while ( getchar() != '\n') ;
printf("Input your operator(+/-):");
scanf("%c", &opr);
while ( getchar() != '\n') ;
printf("\nInput second number:");
fgets(tmp_str, sizeof(tmp_str), stdin);
str_len = strlen(tmp_str);
ptr = tmp_str + str_len -1;
while (ptr >= tmp_str) {
*ptr = 'q';
ptr -= 8;
if (ptr < tmp_str) get = tmp_str;
else get = ptr;
sscanf(get, "%8d", &data);
if(data < 0) {
printf("number < 0 does not support yet\n");
exit(-1);
}
p1 = g_list_new();
if (p1) {
head2 = g_list_preinsert(head2, p1);
p1->data = data;
}
else {
exit(-1);
}
}
g_list_print_number(head2);
int len1 = g_link_get_len(head1);
int len2 = g_link_get_len(head2);
if (opr == '-') {
if (len1 < len2) {
head1 = g_link_opr(head2, head1, opr, len1);
p1 = g_list_new();
head1 = g_list_preinsert(head1, p1);
head1->data = -1;
}
else head1 = g_link_opr(head1, head2, opr, len2);
}
else {
if (len1 < len2) {
head1 = g_link_opr(head2, head1, opr, len1);
}
else head1 = g_link_opr(head1, head2, opr, len2);
}
g_list_print_number(head1);
}
root@ubuntu:data-struct#
=======================一些测试结果===================
加法
root@ubuntu:data-struct# ./a.out
Input first number:99999999999999999999999
****** start of list ******
9999999 99999999 99999999
===== end of list =====
Input your operator(+/-):+
Input second number:44444444444444444444444444444444444444444444444
****** start of list ******
44444444 44444444 44444444 44444444 44444444 44444444 4444444
===== end of list =====
****** start of list ******
44444444 44444444 44444444 44444444 54444444 44444444 4444443
===== end of list =====
不产生负数的减法:
root@ubuntu:data-struct# ./a.out
Input first number:4444444444444444444444444444
****** start of list ******
4444 44444444 44444444 44444444
===== end of list =====
Input your operator(+/-):-
Input second number:3333333333
****** start of list ******
33 33333333
===== end of list =====
****** start of list ******
4444 44444444 44444411 11111111